diff --git a/package-lock.json b/package-lock.json index 797480d34..4ff8bd83f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55,7 +55,8 @@ }, "node_modules/@alcalzone/ansi-tokenize": { "version": "0.1.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.1.3.tgz", + "integrity": "sha512-3yWxPTq3UQ/FY9p1ErPxIyfT64elWaMvM9lIHnaqpyft63tkxodF5aUElYHrdisWve5cETkh1+KBw1yJuW0aRw==", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^4.0.0" @@ -66,7 +67,8 @@ }, "node_modules/@alcalzone/ansi-tokenize/node_modules/ansi-styles": { "version": "6.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "engines": { "node": ">=12" }, @@ -616,7 +618,8 @@ }, "node_modules/@envelop/core": { "version": "5.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@envelop/core/-/core-5.0.2.tgz", + "integrity": "sha512-tVL6OrMe6UjqLosiE+EH9uxh2TQC0469GwF4tE014ugRaDDKKVWwFwZe0TBMlcyHKh5MD4ZxktWo/1hqUxIuhw==", "dependencies": { "@envelop/types": "5.0.0", "tslib": "^2.5.0" @@ -627,7 +630,8 @@ }, "node_modules/@envelop/extended-validation": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@envelop/extended-validation/-/extended-validation-4.1.0.tgz", + "integrity": "sha512-S90LQanW+xg3Lkp2sNiHa2KJnXXpKLucKys05Wk5zpiV0vL0SDX+/cuV+tnDhShWJucunAGi34n8xFCXsUUOkA==", "dependencies": { "@graphql-tools/utils": "^10.0.0", "tslib": "^2.5.0" @@ -1000,7 +1004,8 @@ }, "node_modules/@inkjs/ui": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@inkjs/ui/-/ui-1.0.0.tgz", + "integrity": "sha512-JAVX5ntXG3QokXsGelobIc1ORkTQiJU4XiemUoMUzVaZkBpwzOD7NkMm0qzKvysDyrE1nD6keFHRhwsRvhVamw==", "dependencies": { "chalk": "^5.2.0", "cli-spinners": "^2.9.0", @@ -1016,7 +1021,8 @@ }, "node_modules/@inkjs/ui/node_modules/chalk": { "version": "5.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -1026,7 +1032,8 @@ }, "node_modules/@inkjs/ui/node_modules/cli-spinners": { "version": "2.9.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "engines": { "node": ">=6" }, @@ -1036,7 +1043,8 @@ }, "node_modules/@inkjs/ui/node_modules/escape-string-regexp": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "engines": { "node": ">=12" }, @@ -1046,7 +1054,8 @@ }, "node_modules/@inkjs/ui/node_modules/figures": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", "dependencies": { "escape-string-regexp": "^5.0.0", "is-unicode-supported": "^1.2.0" @@ -1060,7 +1069,8 @@ }, "node_modules/@inkjs/ui/node_modules/is-unicode-supported": { "version": "1.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "engines": { "node": ">=12" }, @@ -3242,8 +3252,9 @@ }, "node_modules/@prisma/client": { "version": "5.21.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.21.1.tgz", + "integrity": "sha512-3n+GgbAZYjaS/k0M03yQsQfR1APbr411r74foknnsGpmhNKBG49VuUkxIU6jORgvJPChoD4WC4PqoHImN1FP0w==", "hasInstallScript": true, - "license": "Apache-2.0", "engines": { "node": ">=16.13" }, @@ -3258,12 +3269,14 @@ }, "node_modules/@prisma/debug": { "version": "5.21.1", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.21.1.tgz", + "integrity": "sha512-uY8SAhcnORhvgtOrNdvWS98Aq/nkQ9QDUxrWAgW8XrCZaI3j2X7zb7Xe6GQSh6xSesKffFbFlkw0c2luHQviZA==" }, "node_modules/@prisma/engines": { "version": "5.21.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.21.1.tgz", + "integrity": "sha512-hGVTldUkIkTwoV8//hmnAAiAchi4oMEKD3aW5H2RrnI50tTdwza7VQbTTAyN3OIHWlK5DVg6xV7X8N/9dtOydA==", "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { "@prisma/debug": "5.21.1", "@prisma/engines-version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36", @@ -3273,11 +3286,13 @@ }, "node_modules/@prisma/engines-version": { "version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36.tgz", + "integrity": "sha512-qvnEflL0//lh44S/T9NcvTMxfyowNeUxTunPcDfKPjyJNrCNf2F1zQLcUv5UHAruECpX+zz21CzsC7V2xAeM7Q==" }, "node_modules/@prisma/fetch-engine": { "version": "5.21.1", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.21.1.tgz", + "integrity": "sha512-70S31vgpCGcp9J+mh/wHtLCkVezLUqe/fGWk3J3JWZIN7prdYSlr1C0niaWUyNK2VflLXYi8kMjAmSxUVq6WGQ==", "dependencies": { "@prisma/debug": "5.21.1", "@prisma/engines-version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36", @@ -3286,7 +3301,8 @@ }, "node_modules/@prisma/generator-helper": { "version": "5.21.1", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@prisma/generator-helper/-/generator-helper-5.21.1.tgz", + "integrity": "sha512-56+FLaNGO7uKIEjN5asV7L0cAWqTc+IoyFbtafYnzfvBS3HURgT+l9UGHrHfPO5EWFiot3my3UOJ/hGZfhNPbA==", "peer": true, "dependencies": { "@prisma/debug": "5.21.1" @@ -3294,14 +3310,16 @@ }, "node_modules/@prisma/get-platform": { "version": "5.21.1", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.21.1.tgz", + "integrity": "sha512-sRxjL3Igst3ct+e8ya/x//cDXmpLbZQ5vfps2N4tWl4VGKQAmym77C/IG/psSMsQKszc8uFC/q1dgmKFLUgXZQ==", "dependencies": { "@prisma/debug": "5.21.1" } }, "node_modules/@prisma/internals": { "version": "5.21.1", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@prisma/internals/-/internals-5.21.1.tgz", + "integrity": "sha512-XCjJUUDBwT0ioLrTfUKA/YsVs5gtWtMisxRssGS5tgqVaVzc8XEY01avtYIzyhz8RDLn7QlecTQGHW+5J9+w6Q==", "peer": true, "dependencies": { "@prisma/debug": "5.21.1", @@ -3317,12 +3335,14 @@ }, "node_modules/@prisma/prisma-schema-wasm": { "version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@prisma/prisma-schema-wasm/-/prisma-schema-wasm-5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36.tgz", + "integrity": "sha512-JJnZ7A0CSW4SNFSWe2/GexJ/Z5s69+3UqbsBuGxJe7EQyVgw/hmskmhFmM4gccihh9PA2hlDip5kmraAfO7vSA==", "peer": true }, "node_modules/@prisma/schema-files-loader": { "version": "5.21.1", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@prisma/schema-files-loader/-/schema-files-loader-5.21.1.tgz", + "integrity": "sha512-rcZgI4rSq5tlieWQ5e+AfyjquwQ+d2vCecvbf9qvfcvs/Nw5FbjAPTLEx9l4g/iW4qgc0CTPLr19azD3npwHQw==", "peer": true, "dependencies": { "@prisma/prisma-schema-wasm": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36", @@ -3331,7 +3351,8 @@ }, "node_modules/@prisma/schema-files-loader/node_modules/fs-extra": { "version": "11.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", "peer": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -3601,7 +3622,8 @@ }, "node_modules/@ts-morph/common": { "version": "0.24.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.24.0.tgz", + "integrity": "sha512-c1xMmNHWpNselmpIqursHeOHHBTIsJLbB+NuovbTTRCNiTLEr/U9dbJ8qy0jd/O2x5pc3seWuOUN5R2IoOTp8A==", "peer": true, "dependencies": { "fast-glob": "^3.3.2", @@ -3612,7 +3634,8 @@ }, "node_modules/@ts-morph/common/node_modules/mkdirp": { "version": "3.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "peer": true, "bin": { "mkdirp": "dist/cjs/src/bin.js" @@ -3756,8 +3779,9 @@ }, "node_modules/@types/figlet": { "version": "1.7.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/figlet/-/figlet-1.7.0.tgz", + "integrity": "sha512-KwrT7p/8Eo3Op/HBSIwGXOsTZKYiM9NpWRBJ5sVjWP/SmlS+oxxRvJht/FNAtliJvja44N3ul1yATgohnVBV0Q==", + "dev": true }, "node_modules/@types/graceful-fs": { "version": "4.1.9", @@ -3768,7 +3792,8 @@ }, "node_modules/@types/graphql-fields": { "version": "1.3.9", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/graphql-fields/-/graphql-fields-1.3.9.tgz", + "integrity": "sha512-HynTnp1HrE58uYcFcAK5UOfdrHSOIHDLCjvMU4yCmQLMj21uo7ZiZqnDGrD27pgCgHH5a1e8GYNK98Ndmma7ig==", "peer": true, "dependencies": { "graphql": "*" @@ -3790,8 +3815,10 @@ }, "node_modules/@types/ink": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/ink/-/ink-2.0.3.tgz", + "integrity": "sha512-DYKIKEJqhsGfQ/jgX0t9BzfHmBJ/9dBBT2MDsHAQRAfOPhEe7LZm5QeNBx1J34/e108StCPuJ3r4bh1y38kCJA==", + "deprecated": "This is a stub types definition. ink provides its own type definitions, so you do not need this installed.", "dev": true, - "license": "MIT", "dependencies": { "ink": "*" } @@ -3900,8 +3927,9 @@ }, "node_modules/@types/prop-types": { "version": "15.7.13", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "devOptional": true }, "node_modules/@types/qs": { "version": "6.9.15", @@ -3915,8 +3943,9 @@ }, "node_modules/@types/react": { "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "devOptional": true, - "license": "MIT", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3974,7 +4003,8 @@ }, "node_modules/@types/yoga-layout": { "version": "1.9.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz", + "integrity": "sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.14.1", @@ -4566,7 +4596,8 @@ }, "node_modules/arg": { "version": "5.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", "peer": true }, "node_modules/argparse": { @@ -4738,7 +4769,8 @@ }, "node_modules/auto-bind": { "version": "5.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-5.0.1.tgz", + "integrity": "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -5419,7 +5451,8 @@ }, "node_modules/cli-boxes": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "engines": { "node": ">=10" }, @@ -5582,12 +5615,14 @@ }, "node_modules/code-block-writer": { "version": "13.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", "peer": true }, "node_modules/code-excerpt": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", "dependencies": { "convert-to-spaces": "^2.0.1" }, @@ -5956,7 +5991,8 @@ }, "node_modules/convert-to-spaces": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -6151,8 +6187,9 @@ }, "node_modules/csstype": { "version": "3.1.3", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true }, "node_modules/cz-conventional-changelog": { "version": "3.3.0", @@ -7438,7 +7475,8 @@ }, "node_modules/figlet": { "version": "1.8.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.8.0.tgz", + "integrity": "sha512-chzvGjd+Sp7KUvPHZv6EXV5Ir3Q7kYNpCr4aHrRW79qFtTefmQZNny+W1pW9kf5zeE6dikku2W50W/wAH2xWgw==", "bin": { "figlet": "bin/index.js" }, @@ -8197,14 +8235,16 @@ }, "node_modules/graphql": { "version": "16.9.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, "node_modules/graphql-fields": { "version": "2.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/graphql-fields/-/graphql-fields-2.0.3.tgz", + "integrity": "sha512-x3VE5lUcR4XCOxPIqaO4CE+bTK8u6gVouOdpQX9+EKHr+scqtK5Pp/l8nIGqIpN1TUlkKE6jDCCycm/WtLRAwA==", "peer": true }, "node_modules/graphql-query-complexity": { @@ -8703,7 +8743,8 @@ }, "node_modules/ink": { "version": "4.4.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ink/-/ink-4.4.1.tgz", + "integrity": "sha512-rXckvqPBB0Krifk5rn/5LvQGmyXwCUpBfmTwbkQNBY9JY8RSl3b8OftBNEYxg4+SWUhEKcPifgope28uL9inlA==", "dependencies": { "@alcalzone/ansi-tokenize": "^0.1.3", "ansi-escapes": "^6.0.0", @@ -8750,7 +8791,8 @@ }, "node_modules/ink-ascii": { "version": "0.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ink-ascii/-/ink-ascii-0.0.4.tgz", + "integrity": "sha512-x6mZTHevoiAHgxrhxMpSc2p0lomq34uyGjwEFkpku7Rhxg30/MBnAi9gCHR17SMmaqRDzQRp1MS9s8Qvd4RHsA==", "dependencies": { "figlet": "^1.2.4", "ink": "^2.6.0", @@ -8763,14 +8805,16 @@ }, "node_modules/ink-ascii/node_modules/ansi-regex": { "version": "4.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "engines": { "node": ">=6" } }, "node_modules/ink-ascii/node_modules/ansi-styles": { "version": "4.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { "color-convert": "^2.0.1" }, @@ -8783,14 +8827,16 @@ }, "node_modules/ink-ascii/node_modules/arrify": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "engines": { "node": ">=8" } }, "node_modules/ink-ascii/node_modules/auto-bind": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", + "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==", "engines": { "node": ">=8" }, @@ -8800,7 +8846,8 @@ }, "node_modules/ink-ascii/node_modules/chalk": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -8811,7 +8858,8 @@ }, "node_modules/ink-ascii/node_modules/cli-truncate": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dependencies": { "slice-ansi": "^3.0.0", "string-width": "^4.2.0" @@ -8825,7 +8873,8 @@ }, "node_modules/ink-ascii/node_modules/color-convert": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { "color-name": "~1.1.4" }, @@ -8835,22 +8884,26 @@ }, "node_modules/ink-ascii/node_modules/color-name": { "version": "1.1.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/ink-ascii/node_modules/emoji-regex": { "version": "7.0.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "node_modules/ink-ascii/node_modules/has-flag": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { "node": ">=8" } }, "node_modules/ink-ascii/node_modules/ink": { "version": "2.7.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ink/-/ink-2.7.1.tgz", + "integrity": "sha512-s7lJuQDJEdjqtaIWhp3KYHl6WV3J04U9zoQ6wVc+Xoa06XM27SXUY57qC5DO46xkF0CfgXMKkKNcgvSu/SAEpA==", "dependencies": { "ansi-escapes": "^4.2.1", "arrify": "^2.0.1", @@ -8886,14 +8939,16 @@ }, "node_modules/ink-ascii/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { "node": ">=8" } }, "node_modules/ink-ascii/node_modules/log-update": { "version": "3.4.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-3.4.0.tgz", + "integrity": "sha512-ILKe88NeMt4gmDvk/eb615U/IVn7K9KWGkoYbdatQ69Z65nj1ZzjM6fHXfcs0Uge+e+EGnMW7DY4T9yko8vWFg==", "dependencies": { "ansi-escapes": "^3.2.0", "cli-cursor": "^2.1.0", @@ -8908,14 +8963,16 @@ }, "node_modules/ink-ascii/node_modules/log-update/node_modules/ansi-escapes": { "version": "3.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "engines": { "node": ">=4" } }, "node_modules/ink-ascii/node_modules/log-update/node_modules/ansi-styles": { "version": "3.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { "color-convert": "^1.9.0" }, @@ -8925,7 +8982,8 @@ }, "node_modules/ink-ascii/node_modules/log-update/node_modules/cli-cursor": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", "dependencies": { "restore-cursor": "^2.0.0" }, @@ -8935,25 +8993,29 @@ }, "node_modules/ink-ascii/node_modules/log-update/node_modules/color-convert": { "version": "1.9.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { "color-name": "1.1.3" } }, "node_modules/ink-ascii/node_modules/log-update/node_modules/color-name": { "version": "1.1.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/ink-ascii/node_modules/log-update/node_modules/is-fullwidth-code-point": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "engines": { "node": ">=4" } }, "node_modules/ink-ascii/node_modules/log-update/node_modules/string-width": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dependencies": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -8965,7 +9027,8 @@ }, "node_modules/ink-ascii/node_modules/log-update/node_modules/strip-ansi": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dependencies": { "ansi-regex": "^4.1.0" }, @@ -8975,7 +9038,8 @@ }, "node_modules/ink-ascii/node_modules/log-update/node_modules/wrap-ansi": { "version": "5.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dependencies": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -8987,14 +9051,16 @@ }, "node_modules/ink-ascii/node_modules/mimic-fn": { "version": "1.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "engines": { "node": ">=4" } }, "node_modules/ink-ascii/node_modules/onetime": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "dependencies": { "mimic-fn": "^1.0.0" }, @@ -9004,7 +9070,8 @@ }, "node_modules/ink-ascii/node_modules/react": { "version": "16.14.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -9016,7 +9083,8 @@ }, "node_modules/ink-ascii/node_modules/react-reconciler": { "version": "0.24.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.24.0.tgz", + "integrity": "sha512-gAGnwWkf+NOTig9oOowqid9O0HjTDC+XVGBCAmJYYJ2A2cN/O4gDdIuuUQjv8A4v6GDwVfJkagpBBLW5OW9HSw==", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -9032,7 +9100,8 @@ }, "node_modules/ink-ascii/node_modules/restore-cursor": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", "dependencies": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" @@ -9043,7 +9112,8 @@ }, "node_modules/ink-ascii/node_modules/scheduler": { "version": "0.18.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", + "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -9051,7 +9121,8 @@ }, "node_modules/ink-ascii/node_modules/slice-ansi": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -9063,7 +9134,8 @@ }, "node_modules/ink-ascii/node_modules/string-length": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", + "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", "dependencies": { "astral-regex": "^1.0.0", "strip-ansi": "^5.2.0" @@ -9074,14 +9146,16 @@ }, "node_modules/ink-ascii/node_modules/string-length/node_modules/astral-regex": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "engines": { "node": ">=4" } }, "node_modules/ink-ascii/node_modules/string-length/node_modules/strip-ansi": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dependencies": { "ansi-regex": "^4.1.0" }, @@ -9091,7 +9165,8 @@ }, "node_modules/ink-ascii/node_modules/supports-color": { "version": "7.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { "has-flag": "^4.0.0" }, @@ -9101,7 +9176,8 @@ }, "node_modules/ink-ascii/node_modules/widest-line": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dependencies": { "string-width": "^4.0.0" }, @@ -9111,7 +9187,8 @@ }, "node_modules/ink-ascii/node_modules/wrap-ansi": { "version": "6.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -9123,7 +9200,8 @@ }, "node_modules/ink/node_modules/ansi-escapes": { "version": "6.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", "engines": { "node": ">=14.16" }, @@ -9133,7 +9211,8 @@ }, "node_modules/ink/node_modules/ansi-regex": { "version": "6.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "engines": { "node": ">=12" }, @@ -9143,7 +9222,8 @@ }, "node_modules/ink/node_modules/ansi-styles": { "version": "6.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "engines": { "node": ">=12" }, @@ -9153,7 +9233,8 @@ }, "node_modules/ink/node_modules/chalk": { "version": "5.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -9163,7 +9244,8 @@ }, "node_modules/ink/node_modules/cli-cursor": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dependencies": { "restore-cursor": "^4.0.0" }, @@ -9176,11 +9258,13 @@ }, "node_modules/ink/node_modules/emoji-regex": { "version": "9.2.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/ink/node_modules/indent-string": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "engines": { "node": ">=12" }, @@ -9190,7 +9274,8 @@ }, "node_modules/ink/node_modules/is-ci": { "version": "3.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dependencies": { "ci-info": "^3.2.0" }, @@ -9200,7 +9285,8 @@ }, "node_modules/ink/node_modules/restore-cursor": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -9214,7 +9300,8 @@ }, "node_modules/ink/node_modules/slice-ansi": { "version": "6.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-6.0.0.tgz", + "integrity": "sha512-6bn4hRfkTvDfUoEQYkERg0BVF1D0vrX9HEkMl08uDiNWvVvjylLHvZFZWkDo6wjT8tUctbYl1nCOuE66ZTaUtA==", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^4.0.0" @@ -9228,7 +9315,8 @@ }, "node_modules/ink/node_modules/string-width": { "version": "5.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -9243,7 +9331,8 @@ }, "node_modules/ink/node_modules/strip-ansi": { "version": "7.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -9256,7 +9345,8 @@ }, "node_modules/ink/node_modules/type-fest": { "version": "0.12.0", - "license": "(MIT OR CC0-1.0)", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.12.0.tgz", + "integrity": "sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg==", "engines": { "node": ">=10" }, @@ -9266,7 +9356,8 @@ }, "node_modules/ink/node_modules/wrap-ansi": { "version": "8.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -9603,7 +9694,8 @@ }, "node_modules/is-lower-case": { "version": "2.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz", + "integrity": "sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==", "dependencies": { "tslib": "^2.0.3" } @@ -9793,7 +9885,8 @@ }, "node_modules/is-upper-case": { "version": "2.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz", + "integrity": "sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==", "dependencies": { "tslib": "^2.0.3" } @@ -10745,7 +10838,8 @@ }, "node_modules/jest-mock-extended": { "version": "4.0.0-beta1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-4.0.0-beta1.tgz", + "integrity": "sha512-MYcI0wQu3ceNhqKoqAJOdEfsVMamAFqDTjoLN5Y45PAG3iIm4WGnhOu0wpMjlWCexVPO71PMoNir9QrGXrnIlw==", "dependencies": { "ts-essentials": "^10.0.2" }, @@ -12496,7 +12590,8 @@ }, "node_modules/lodash.throttle": { "version": "4.1.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" }, "node_modules/lodash.uniq": { "version": "4.5.0", @@ -12688,7 +12783,8 @@ }, "node_modules/loose-envify": { "version": "1.4.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -14453,7 +14549,8 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { "node": ">=0.10.0" } @@ -15096,14 +15193,16 @@ }, "node_modules/patch-console": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/patch-console/-/patch-console-2.0.0.tgz", + "integrity": "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, "node_modules/path-browserify": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "peer": true }, "node_modules/path-exists": { @@ -15261,7 +15360,8 @@ }, "node_modules/pluralize": { "version": "8.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "peer": true, "engines": { "node": ">=4" @@ -15344,8 +15444,9 @@ }, "node_modules/prisma": { "version": "5.21.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.21.1.tgz", + "integrity": "sha512-PB+Iqzld/uQBPaaw2UVIk84kb0ITsLajzsxzsadxxl54eaU5Gyl2/L02ysivHxK89t7YrfQJm+Ggk37uvM70oQ==", "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { "@prisma/engines": "5.21.1" }, @@ -15361,7 +15462,8 @@ }, "node_modules/prisma-mock": { "version": "0.10.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/prisma-mock/-/prisma-mock-0.10.3.tgz", + "integrity": "sha512-VOAsIU/gtWDUOyY2POz9HhpMVNeXhVAJdVeLLQs99j1KXcdw8nys/e6K1mKeVvt/Pc3RgE8DeEdCNPMrQTFwVA==", "dependencies": { "jest-mock-extended": "^3.0.6" }, @@ -15371,7 +15473,8 @@ }, "node_modules/prisma-mock/node_modules/jest-mock-extended": { "version": "3.0.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.7.tgz", + "integrity": "sha512-7lsKdLFcW9B9l5NzZ66S/yTQ9k8rFtnwYdCNuRU/81fqDWicNDVhitTSPnrGmNeNm0xyw0JHexEOShrIKRCIRQ==", "dependencies": { "ts-essentials": "^10.0.0" }, @@ -15447,7 +15550,8 @@ }, "node_modules/prop-types": { "version": "15.8.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -15456,7 +15560,8 @@ }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/proto-list": { "version": "1.2.4", @@ -15532,7 +15637,8 @@ }, "node_modules/react": { "version": "18.3.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "dependencies": { "loose-envify": "^1.1.0" }, @@ -15546,7 +15652,8 @@ }, "node_modules/react-json-view-lite": { "version": "1.5.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.5.0.tgz", + "integrity": "sha512-nWqA1E4jKPklL2jvHWs6s+7Na0qNgw9HCP6xehdQJeg6nPBTFZgGwyko9Q0oj+jQWKTTVRS30u0toM5wiuL3iw==", "engines": { "node": ">=14" }, @@ -15556,7 +15663,8 @@ }, "node_modules/react-reconciler": { "version": "0.29.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.2.tgz", + "integrity": "sha512-zZQqIiYgDCTP/f1N/mAR10nJGrPD2ZR+jDSEsKWJHYC7Cm2wodlwbR3upZRdC3cjIjSlTLNVyO7Iu0Yy7t2AYg==", "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -16144,14 +16252,16 @@ }, "node_modules/scheduler": { "version": "0.23.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "dependencies": { "loose-envify": "^1.1.0" } }, "node_modules/semver": { "version": "7.6.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -17012,7 +17122,8 @@ }, "node_modules/ts-essentials": { "version": "10.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-10.0.2.tgz", + "integrity": "sha512-Xwag0TULqriaugXqVdDiGZ5wuZpqABZlpwQ2Ho4GDyiu/R2Xjkp/9+zcFxL7uzeLl/QCPrflnvpVYyS3ouT7Zw==", "peerDependencies": { "typescript": ">=4.5.0" }, @@ -17082,7 +17193,8 @@ }, "node_modules/ts-morph": { "version": "23.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-23.0.0.tgz", + "integrity": "sha512-FcvFx7a9E8TUe6T3ShihXJLiJOiqyafzFKUO4aqIHDUCIvADdGNShcbc2W5PMr3LerXRv7mafvFZ9lRENxJmug==", "peer": true, "dependencies": { "@ts-morph/common": "~0.24.0", @@ -17314,6 +17426,8 @@ }, "node_modules/type-graphql": { "version": "2.0.0-rc.2", + "resolved": "https://registry.npmjs.org/type-graphql/-/type-graphql-2.0.0-rc.2.tgz", + "integrity": "sha512-DJ8erG1cmjteMrOhFIkBHOqRM+L+wCJxvNjbbj1Y+q2r4HZkB1qOSS4ZD4AaoAfRPAp1yU23gMtmzf0jen/FFA==", "funding": [ { "type": "github", @@ -17324,7 +17438,6 @@ "url": "https://opencollective.com/typegraphql" } ], - "license": "MIT", "dependencies": { "@graphql-yoga/subscription": "^5.0.0", "@types/node": "*", @@ -17434,7 +17547,8 @@ }, "node_modules/typegraphql-prisma": { "version": "0.28.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/typegraphql-prisma/-/typegraphql-prisma-0.28.0.tgz", + "integrity": "sha512-LMTsYEAteeXhnJRmH2sBWarR8Jc9Um13mtSpi8Vh6G8QUTlp5tRfqMjd+Fw06HS6SBshU6NilZJlsPaz26SQCw==", "peer": true, "dependencies": { "@prisma/generator-helper": "^5.18.0", @@ -17787,7 +17901,8 @@ }, "node_modules/widest-line": { "version": "4.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", "dependencies": { "string-width": "^5.0.1" }, @@ -17800,7 +17915,8 @@ }, "node_modules/widest-line/node_modules/ansi-regex": { "version": "6.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "engines": { "node": ">=12" }, @@ -17810,11 +17926,13 @@ }, "node_modules/widest-line/node_modules/emoji-regex": { "version": "9.2.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/widest-line/node_modules/string-width": { "version": "5.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -17829,7 +17947,8 @@ }, "node_modules/widest-line/node_modules/strip-ansi": { "version": "7.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -18046,7 +18165,8 @@ }, "node_modules/ws": { "version": "8.18.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "engines": { "node": ">=10.0.0" }, @@ -18155,7 +18275,8 @@ }, "node_modules/yoga-layout-prebuilt": { "version": "1.10.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.10.0.tgz", + "integrity": "sha512-YnOmtSbv4MTf7RGJMK0FvZ+KD8OEe/J5BNnR0GHhD8J/XcG/Qvxgszm0Un6FTHWW4uHlTgP0IztiXQnGyIR45g==", "dependencies": { "@types/yoga-layout": "1.9.2" }, @@ -18165,7 +18286,8 @@ }, "node_modules/yoga-wasm-web": { "version": "0.3.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/yoga-wasm-web/-/yoga-wasm-web-0.3.3.tgz", + "integrity": "sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==" }, "packages/api": { "name": "@proto-kit/api", diff --git a/packages/api/src/graphql/modules/BatchStorageResolver.ts b/packages/api/src/graphql/modules/BatchStorageResolver.ts index f4a9e8c50..47fca0ab5 100644 --- a/packages/api/src/graphql/modules/BatchStorageResolver.ts +++ b/packages/api/src/graphql/modules/BatchStorageResolver.ts @@ -21,7 +21,7 @@ export class ComputedBlockModel { blockHashes.map( (blockHash) => blocks.find((block) => block?.hash === blockHash)! ), - proof.proof === MOCK_PROOF ? "mock-proof" : JSON.stringify(proof) + proof.proof === MOCK_PROOF ? MOCK_PROOF : JSON.stringify(proof) ); } diff --git a/packages/common/src/events/EventEmitterProxy.ts b/packages/common/src/events/EventEmitterProxy.ts index 626b057b1..3b055a298 100644 --- a/packages/common/src/events/EventEmitterProxy.ts +++ b/packages/common/src/events/EventEmitterProxy.ts @@ -6,7 +6,11 @@ import type { import { StringKeyOf, UnionToIntersection } from "../types"; import { EventEmitter } from "./EventEmitter"; -import { EventEmittingComponent, EventsRecord } from "./EventEmittingComponent"; +import { + EventEmittingComponent, + EventEmittingContainer, + EventsRecord, +} from "./EventEmittingComponent"; export type CastToEventsRecord = Record extends EventsRecord ? Record @@ -17,7 +21,13 @@ export type ModuleEvents = ? Events : InstanceType extends ModuleContainer ? CastToEventsRecord> - : EventsRecord; + : // & + // (InstanceType extends EventEmittingContainer< + // infer ContainerEvents + // > + // ? ContainerEvents + // : {}) + EventsRecord; export type ContainerEvents = { [Key in StringKeyOf]: ModuleEvents; @@ -27,7 +37,7 @@ export type FlattenObject> = UnionToIntersection; export type FlattenedContainerEvents = - FlattenObject>; + FlattenObject>; // & FlattenObject; export class EventEmitterProxy< Modules extends ModulesRecord, @@ -45,10 +55,24 @@ export class EventEmitterProxy< this.emit(events, ...args); }); } + if (this.isEventEmittingContainer(module)) { + module.containerEvents.onAll((events: any, args: any[]) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.emit(events, ...args); + }); + } } }); } + private isEventEmittingContainer( + module: any + ): module is EventEmittingContainer { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const emitter = module.containerEvents; + return emitter !== undefined && emitter instanceof EventEmitter; + } + private isEventEmitter( module: any ): module is EventEmittingComponent { diff --git a/packages/common/src/events/EventEmittingComponent.ts b/packages/common/src/events/EventEmittingComponent.ts index 5f4744f70..ad4609dbb 100644 --- a/packages/common/src/events/EventEmittingComponent.ts +++ b/packages/common/src/events/EventEmittingComponent.ts @@ -5,3 +5,7 @@ export type EventsRecord = Record; export interface EventEmittingComponent { events: EventEmitter; } + +export interface EventEmittingContainer { + containerEvents: EventEmitter; +} diff --git a/packages/common/src/log.ts b/packages/common/src/log.ts index fbd812a34..e7039a23e 100644 --- a/packages/common/src/log.ts +++ b/packages/common/src/log.ts @@ -25,6 +25,26 @@ function logProvable( } /* eslint-enable */ +const timeMap: Record = {}; + +function time(label = "time") { + timeMap[label] = Date.now(); +} + +function timeLog(label = "time"): string { + const prev = timeMap[label]; + if (prev === undefined) { + return "Label not found"; + } + return `${label} took ${Date.now() - prev}ms`; +} + +function timeEnd(label = "time"): string { + const str = timeLog(label); + delete timeMap[label]; + return str; +} + export const log = { provable: { info: (...args: unknown[]) => { @@ -48,6 +68,24 @@ export const log = { }, }, + time, + + timeLog: { + info: (label?: string) => loglevel.info(timeLog(label)), + debug: (label?: string) => loglevel.debug(timeLog(label)), + error: (label?: string) => loglevel.error(timeLog(label)), + trace: (label?: string) => loglevel.trace(timeLog(label)), + warn: (label?: string) => loglevel.warn(timeLog(label)), + }, + + timeEnd: { + info: (label?: string) => loglevel.info(timeEnd(label)), + debug: (label?: string) => loglevel.debug(timeEnd(label)), + error: (label?: string) => loglevel.error(timeEnd(label)), + trace: (label?: string) => loglevel.trace(timeEnd(label)), + warn: (label?: string) => loglevel.warn(timeEnd(label)), + }, + info: (...args: unknown[]) => { loglevel.info(...args); }, diff --git a/packages/common/src/zkProgrammable/ZkProgrammable.ts b/packages/common/src/zkProgrammable/ZkProgrammable.ts index 01e4701d0..0b5f36fc8 100644 --- a/packages/common/src/zkProgrammable/ZkProgrammable.ts +++ b/packages/common/src/zkProgrammable/ZkProgrammable.ts @@ -7,8 +7,8 @@ import { dummyVerificationKey } from "../dummyVerificationKey"; import { MOCK_PROOF } from "./provableMethod"; const errors = { - appChainNotSet: (name: string) => - new Error(`Appchain was not injected for: ${name}`), + areProofsEnabledNotSet: (name: string) => + new Error(`AreProofsEnabled was not injected for: ${name}`), }; export interface CompileArtifact { @@ -72,6 +72,8 @@ export function verifyToMockable( return verified; } + console.log("VerifyMocked"); + return proof.proof === MOCK_PROOF; }; } @@ -97,25 +99,29 @@ export abstract class ZkProgrammable< PublicInput = undefined, PublicOutput = void, > { - public abstract get appChain(): AreProofsEnabled | undefined; + public abstract get areProofsEnabled(): AreProofsEnabled | undefined; public abstract zkProgramFactory(): PlainZkProgram< PublicInput, PublicOutput >[]; + private zkProgramSingleton?: PlainZkProgram[]; + @Memoize() public get zkProgram(): PlainZkProgram[] { - const zkProgram = this.zkProgramFactory(); + if (this.zkProgramSingleton === undefined) { + this.zkProgramSingleton = this.zkProgramFactory(); + } - return zkProgram.map((bucket) => { - if (!this.appChain) { - throw errors.appChainNotSet(this.constructor.name); + return this.zkProgramSingleton.map((bucket) => { + if (!this.areProofsEnabled) { + throw errors.areProofsEnabledNotSet(this.constructor.name); } return { ...bucket, - verify: verifyToMockable(bucket.verify, this.appChain), - compile: compileToMockable(bucket.compile, this.appChain), + verify: verifyToMockable(bucket.verify, this.areProofsEnabled), + compile: compileToMockable(bucket.compile, this.areProofsEnabled), }; }); } diff --git a/packages/common/src/zkProgrammable/provableMethod.ts b/packages/common/src/zkProgrammable/provableMethod.ts index 3a4827766..aac3504d5 100644 --- a/packages/common/src/zkProgrammable/provableMethod.ts +++ b/packages/common/src/zkProgrammable/provableMethod.ts @@ -24,23 +24,23 @@ export function toProver( ...args: ArgumentTypes ) { return async function prover(this: ZkProgrammable) { - const areProofsEnabled = this.appChain?.areProofsEnabled; - if (areProofsEnabled ?? false) { - for (const prog of this.zkProgram) { - if (Object.keys(prog.methods).includes(methodName)) { - const programProvableMethod = prog.methods[methodName]; - // eslint-disable-next-line no-await-in-loop - return await Reflect.apply(programProvableMethod, this, args); - } - } + const { areProofsEnabled } = this.areProofsEnabled!; + + const zkProgram = this.zkProgram.find((prog) => + Object.keys(prog.methods).includes(methodName) + ); + + if (zkProgram === undefined) { + throw new Error("Correct ZkProgram not found"); + } + + if (areProofsEnabled) { + const programProvableMethod = zkProgram.methods[methodName]; + return await Reflect.apply(programProvableMethod, this, args); } - // create a mock proof by simulating method execution in JS + // create a mock proof by simulating method> execution in JS const publicOutput = await Reflect.apply(simulatedMethod, this, args); - const zkProgram = - this.zkProgram.find((prog) => { - return Object.keys(prog.methods).includes(methodName); - }) ?? this.zkProgram[0]; return new zkProgram.Proof({ proof: MOCK_PROOF, diff --git a/packages/common/test/zkProgrammable/ZkProgrammable.test.ts b/packages/common/test/zkProgrammable/ZkProgrammable.test.ts index 5ada80074..4f606954b 100644 --- a/packages/common/test/zkProgrammable/ZkProgrammable.test.ts +++ b/packages/common/test/zkProgrammable/ZkProgrammable.test.ts @@ -39,7 +39,7 @@ class TestProgrammable extends ZkProgrammable< TestPublicInput, TestPublicOutput > { - public appChain: AreProofsEnabled = appChainMock; + public areProofsEnabled: AreProofsEnabled = appChainMock; @provableMethod() public async foo(publicInput: TestPublicInput, bar: Balance) { @@ -97,7 +97,7 @@ class TestProgrammable extends ZkProgrammable< } class OtherTestProgrammable extends ZkProgrammable { - public appChain: AreProofsEnabled = appChainMock; + public areProofsEnabled: AreProofsEnabled = appChainMock; public constructor(public testProgrammable: TestProgrammable) { super(); @@ -183,7 +183,7 @@ describe("zkProgrammable", () => { (areProofsEnabled, { verificationKey, shouldVerifyMockProofs }) => { beforeAll(async () => { testProgrammable = new TestProgrammable(); - testProgrammable.appChain.setProofsEnabled(areProofsEnabled); + testProgrammable.areProofsEnabled.setProofsEnabled(areProofsEnabled); zkProgramFactorySpy = jest.spyOn(testProgrammable, "zkProgramFactory"); artifact = await testProgrammable.zkProgram[0].compile(); }, 500_000); diff --git a/packages/deployment/src/queue/BullQueue.ts b/packages/deployment/src/queue/BullQueue.ts index c7fe8d5e0..bd884670a 100644 --- a/packages/deployment/src/queue/BullQueue.ts +++ b/packages/deployment/src/queue/BullQueue.ts @@ -14,6 +14,7 @@ export interface BullQueueConfig { port: number; username?: string; password?: string; + db?: number; }; retryAttempts?: number; } @@ -25,6 +26,8 @@ export class BullQueue extends SequencerModule implements TaskQueue { + private activePromise?: Promise; + public createWorker( name: string, executor: (data: TaskPayload) => Promise, @@ -32,10 +35,32 @@ export class BullQueue ): Closeable { const worker = new Worker( name, - async (job) => await executor(job.data), + async (job) => { + // This weird promise logic is needed to make sure the worker is not proving in parallel + // This is by far not optimal - since it still picks up 1 task per queue but waits until + // computing them, so that leads to bad performance over multiple workers. + // For that we need to restructure tasks to be flowing through a single queue however + while (this.activePromise !== undefined) { + // eslint-disable-next-line no-await-in-loop + await this.activePromise; + } + let resOutside: () => void = () => {}; + const promise = new Promise((res) => { + resOutside = res; + }); + this.activePromise = promise; + + const result = await executor(job.data); + this.activePromise = undefined; + void resOutside(); + + return result; + }, { concurrency: options?.concurrency ?? 1, connection: this.config.redis, + stalledInterval: 60000, // 1 minute + lockDuration: 60000, // 1 minute metrics: { maxDataPoints: MetricsTime.ONE_HOUR * 24 }, } @@ -68,6 +93,7 @@ export class BullQueue name: queueName, async addTask(payload: TaskPayload): Promise<{ taskId: string }> { + log.debug("Adding task: ", payload); const job = await queue.add(queueName, payload, { attempts: retryAttempts ?? 2, }); @@ -76,14 +102,25 @@ export class BullQueue async onCompleted(listener: (payload: TaskPayload) => Promise) { events.on("completed", async (result) => { - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - await listener(JSON.parse(result.returnvalue) as TaskPayload); + log.debug("Completed task: ", result); + try { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + await listener(result.returnvalue as unknown as TaskPayload); + } catch (e) { + // Catch error explicitly since this promise is dangling, + // therefore any error will be voided as well + log.error(e); + } + }); + events.on("error", async (error) => { + log.error("Error in worker", error); }); await events.waitUntilReady(); }, async close(): Promise { await events.close(); + await queue.drain(); await queue.close(); }, }; diff --git a/packages/library/src/sequencer/SimpleSequencerModules.ts b/packages/library/src/sequencer/SimpleSequencerModules.ts index a35a492ad..2d50200e4 100644 --- a/packages/library/src/sequencer/SimpleSequencerModules.ts +++ b/packages/library/src/sequencer/SimpleSequencerModules.ts @@ -10,7 +10,7 @@ import { BlockTrigger, Database, SequencerModule, - ProtocolStartupModule, + SequencerStartupModule, } from "@proto-kit/sequencer"; import { TypedClass, ModulesConfig } from "@proto-kit/common"; @@ -18,8 +18,8 @@ type PreconfiguredSimpleSequencerModulesRecord = { Mempool: typeof PrivateMempool; BatchProducerModule: typeof BatchProducerModule; BlockProducerModule: typeof BlockProducerModule; - ProtocolStartupModule: TypedClass< - ProtocolStartupModule & SequencerModule + SequencerStartupModule: TypedClass< + SequencerStartupModule & SequencerModule >; }; @@ -90,7 +90,7 @@ export class SimpleSequencerModules { BlockTrigger, TaskQueue, ...reducedModules, - ProtocolStartupModule, + SequencerStartupModule, } satisfies SimpleSequencerModulesRecord; } @@ -102,7 +102,7 @@ export class SimpleSequencerModules { Mempool: {}, BatchProducerModule: {}, - ProtocolStartupModule: {}, + SequencerStartupModule: {}, } satisfies ModulesConfig; } diff --git a/packages/module/src/runtime/Runtime.ts b/packages/module/src/runtime/Runtime.ts index 5f04d8708..32d9050c6 100644 --- a/packages/module/src/runtime/Runtime.ts +++ b/packages/module/src/runtime/Runtime.ts @@ -76,8 +76,8 @@ export class RuntimeZkProgrammable< super(); } - public get appChain() { - return this.runtime.appChain; + public get areProofsEnabled() { + return this.runtime.areProofsEnabled; } public zkProgramFactory(): PlainZkProgram[] { @@ -299,7 +299,7 @@ export class Runtime this.useDependencyFactory(this.container.resolve(MethodIdFactory)); } - public get appChain(): AreProofsEnabled | undefined { + public get areProofsEnabled(): AreProofsEnabled | undefined { return this.container.resolve("AreProofsEnabled"); } diff --git a/packages/module/src/runtime/RuntimeEnvironment.ts b/packages/module/src/runtime/RuntimeEnvironment.ts index 5e2b7d73e..f145799cb 100644 --- a/packages/module/src/runtime/RuntimeEnvironment.ts +++ b/packages/module/src/runtime/RuntimeEnvironment.ts @@ -9,7 +9,7 @@ import { MethodIdResolver } from "./MethodIdResolver"; export interface RuntimeEnvironment extends WithZkProgrammable { - get appChain(): AreProofsEnabled | undefined; + get areProofsEnabled(): AreProofsEnabled | undefined; get stateService(): SimpleAsyncStateService; get stateServiceProvider(): StateServiceProvider; get methodIdResolver(): MethodIdResolver; diff --git a/packages/module/test/modules/Balances.test.ts b/packages/module/test/modules/Balances.test.ts index a425c18fe..6fbf0eb9d 100644 --- a/packages/module/test/modules/Balances.test.ts +++ b/packages/module/test/modules/Balances.test.ts @@ -68,7 +68,7 @@ describe("balances", () => { it("should compile and prove a method execution", async () => { expect.assertions(3); - runtime.zkProgrammable.appChain?.setProofsEnabled(true); + runtime.zkProgrammable.areProofsEnabled?.setProofsEnabled(true); const executionContext = container.resolve(RuntimeMethodExecutionContext); executionContext.setup({ @@ -90,7 +90,7 @@ describe("balances", () => { const verified = await runtime.zkProgrammable.zkProgram[0].verify(proof); - runtime.zkProgrammable.appChain?.setProofsEnabled(false); + runtime.zkProgrammable.areProofsEnabled?.setProofsEnabled(false); expect(verified).toBe(true); diff --git a/packages/persistance/test-integration/PrismaBlockProduction.test.ts b/packages/persistance/test-integration/PrismaBlockProduction.test.ts index 92b55d1b7..2366f3c57 100644 --- a/packages/persistance/test-integration/PrismaBlockProduction.test.ts +++ b/packages/persistance/test-integration/PrismaBlockProduction.test.ts @@ -36,7 +36,7 @@ describe("prisma integration", () => { }, }); - await appChain.start(container.createChildContainer()); + await appChain.start(false, container.createChildContainer()); const db = appChain.sequencer.resolve("Database"); await db.prisma.pruneDatabase(); @@ -77,7 +77,7 @@ describe("prisma integration", () => { expectDefined(block); // Check equality of block - const blockStorage = await appChain.sequencer.resolveOrFail( + const blockStorage = appChain.sequencer.resolveOrFail( "BlockStorage", PrismaBlockStorage ); @@ -124,7 +124,7 @@ describe("prisma integration", () => { expectDefined(batch); // Check equality of batch - const batchStorage = await appChain.sequencer.resolveOrFail( + const batchStorage = appChain.sequencer.resolveOrFail( "BatchStorage", PrismaBatchStore ); diff --git a/packages/persistance/test-integration/utils.ts b/packages/persistance/test-integration/utils.ts index 4c0dbb31b..c0476478e 100644 --- a/packages/persistance/test-integration/utils.ts +++ b/packages/persistance/test-integration/utils.ts @@ -31,7 +31,7 @@ import { Sequencer, BlockProducerModule, VanillaTaskWorkerModules, - ProtocolStartupModule, + SequencerStartupModule, } from "@proto-kit/sequencer"; import { Bool, PrivateKey, PublicKey, Struct } from "o1js"; @@ -114,7 +114,7 @@ export function createPrismaAppchain( BlockProducerModule, BlockTrigger: ManualBlockTrigger, TaskQueue: LocalTaskQueue, - ProtocolStartupModule, + SequencerStartupModule, }, }), modules: { @@ -161,7 +161,7 @@ export function createPrismaAppchain( TaskQueue: { simulatedDuration: 0, }, - ProtocolStartupModule: {}, + SequencerStartupModule: {}, }, Signer: { signer: PrivateKey.random(), diff --git a/packages/protocol/src/hooks/NoopSettlementHook.ts b/packages/protocol/src/hooks/NoopSettlementHook.ts index 5a0f3af5d..166ff678f 100644 --- a/packages/protocol/src/hooks/NoopSettlementHook.ts +++ b/packages/protocol/src/hooks/NoopSettlementHook.ts @@ -1,18 +1,18 @@ import { injectable } from "tsyringe"; import { noop } from "@proto-kit/common"; -import { SmartContract } from "o1js"; import { ProvableSettlementHook, SettlementHookInputs, } from "../settlement/modularity/ProvableSettlementHook"; +import { SettlementSmartContractBase } from "../settlement/contracts/SettlementSmartContract"; @injectable() export class NoopSettlementHook extends ProvableSettlementHook< Record > { public async beforeSettlement( - contract: SmartContract, + contract: SettlementSmartContractBase, state: SettlementHookInputs ) { noop(); diff --git a/packages/protocol/src/protocol/Protocol.ts b/packages/protocol/src/protocol/Protocol.ts index 13c21a24e..f9ebb6fdc 100644 --- a/packages/protocol/src/protocol/Protocol.ts +++ b/packages/protocol/src/protocol/Protocol.ts @@ -26,6 +26,7 @@ import { ProtocolModule } from "./ProtocolModule"; import { ProvableTransactionHook } from "./ProvableTransactionHook"; import { ProtocolEnvironment } from "./ProtocolEnvironment"; import { ProvableBlockHook } from "./ProvableBlockHook"; +import { TransitioningProtocolModule } from "./TransitioningProtocolModule"; const PROTOCOL_INJECTION_TOKENS: Record = { ProvableTransactionHook: "ProvableTransactionHook", @@ -94,7 +95,7 @@ export class Protocol< log.debug(`Decorated ${moduleName}`); containedModule.protocol = this; - if (containedModule instanceof ProvableTransactionHook) { + if (containedModule instanceof TransitioningProtocolModule) { containedModule.name = moduleName; } diff --git a/packages/protocol/src/protocol/ProtocolModule.ts b/packages/protocol/src/protocol/ProtocolModule.ts index bac4e01b6..18c3c4877 100644 --- a/packages/protocol/src/protocol/ProtocolModule.ts +++ b/packages/protocol/src/protocol/ProtocolModule.ts @@ -13,7 +13,7 @@ export abstract class ProtocolModule< > extends ConfigurableModule { public protocol?: ProtocolEnvironment; - public get appChain(): AreProofsEnabled | undefined { + public get areProofsEnabled(): AreProofsEnabled | undefined { return this.protocol?.getAreProofsEnabled(); } diff --git a/packages/protocol/src/prover/block/BlockProvable.ts b/packages/protocol/src/prover/block/BlockProvable.ts index 5d0f54cbe..913a0f709 100644 --- a/packages/protocol/src/prover/block/BlockProvable.ts +++ b/packages/protocol/src/prover/block/BlockProvable.ts @@ -67,6 +67,9 @@ export class DynamicRuntimeProof extends DynamicProof< static publicInputType = Void; static publicOutputType = MethodPublicOutput; + + // TODO this won't be 0 for proofs-as-args + static maxProofsVerified = 0 as const; } export interface BlockProvable @@ -83,7 +86,7 @@ export interface BlockProvable publicInput: BlockProverPublicInput, networkState: NetworkState, blockWitness: BlockHashMerkleTreeWitness, - stateTransitionProof: StateTransitionProof, + // stateTransitionProof: StateTransitionProof, transactionProof: BlockProverProof ) => Promise; diff --git a/packages/protocol/src/prover/block/BlockProver.ts b/packages/protocol/src/prover/block/BlockProver.ts index 04cd1440f..50a0785ec 100644 --- a/packages/protocol/src/prover/block/BlockProver.ts +++ b/packages/protocol/src/prover/block/BlockProver.ts @@ -146,8 +146,8 @@ export class BlockProverProgrammable extends ZkProgrammable< super(); } - public get appChain(): AreProofsEnabled | undefined { - return this.prover.appChain; + public get areProofsEnabled(): AreProofsEnabled | undefined { + return this.prover.areProofsEnabled; } /** @@ -477,7 +477,7 @@ export class BlockProverProgrammable extends ZkProgrammable< publicInput: BlockProverPublicInput, networkState: NetworkState, blockWitness: BlockHashMerkleTreeWitness, - stateTransitionProof: StateTransitionProof, + // stateTransitionProof: StateTransitionProof, transactionProof: BlockProverProof ): Promise { const state: BlockProverState = { @@ -519,24 +519,28 @@ export class BlockProverProgrammable extends ZkProgrammable< "TransactionProof starting incomingMessagesHash not matching" ); + // TODO Reintroduce ST Proofs // Verify ST Proof only if STs have been emitted, // otherwise we can input a dummy proof - const stsEmitted = stateTransitionProof.publicOutput.stateTransitionsHash - .equals(0) - .and(stateTransitionProof.publicOutput.protocolTransitionsHash.equals(0)) - .not(); - stateTransitionProof.verifyIf(stsEmitted); + // const stsEmitted = stateTransitionProof.publicOutput.stateTransitionsHash + // .equals(0) + // .and(stateTransitionProof.publicOutput.protocolTransitionsHash.equals(0)) + // .not(); + // Provable.log("VerifyIf 1", stsEmitted); + // stateTransitionProof.verifyIf(Bool(false)); + // stateTransitionProof.verifyIf(stsEmitted); // Verify Transaction proof if it has at least 1 tx - i.e. the // input and output doesn't match fully // We have to compare the whole input and output because we can make no // assumptions about the values, since it can be an arbitrary dummy-proof const txProofOutput = transactionProof.publicOutput; - const verifyTransactionProof = txProofOutput.equals( + const isEmptyTransition = txProofOutput.equals( transactionProof.publicInput, txProofOutput.closed ); - transactionProof.verifyIf(verifyTransactionProof.not()); + Provable.log("VerifyIf 2", isEmptyTransition.not()); + transactionProof.verifyIf(isEmptyTransition.not()); // 2. Execute beforeBlock hooks const beforeBlockResult = await this.executeBlockHooks( @@ -545,12 +549,12 @@ export class BlockProverProgrammable extends ZkProgrammable< "beforeBlock" ); - const beforeBlockHashList = new StateTransitionReductionList( - ProvableStateTransition - ); - beforeBlockResult.stateTransitions.forEach((st) => { - beforeBlockHashList.push(st.toProvable()); - }); + // const beforeBlockHashList = new StateTransitionReductionList( + // ProvableStateTransition + // ); + // beforeBlockResult.stateTransitions.forEach((st) => { + // beforeBlockHashList.push(st.toProvable()); + // }); // We are reusing protocolSTs here as beforeBlock STs // TODO Not possible atm bcs we can't have a seperation between protocol/runtime state roots, @@ -562,10 +566,10 @@ export class BlockProverProgrammable extends ZkProgrammable< // state.stateRoot = stateTransitionProof.publicInput.protocolStateRoot; // TODO Only for now - beforeBlockHashList.commitment.assertEquals( - Field(0), - "beforeBlock() cannot emit state transitions yet" - ); + // beforeBlockHashList.commitment.assertEquals( + // Field(0), + // "beforeBlock() cannot emit state transitions yet" + // ); // 4. Apply TX-type BlockProof transactionProof.publicInput.networkStateHash.assertEquals( @@ -585,7 +589,7 @@ export class BlockProverProgrammable extends ZkProgrammable< transactionProof.publicOutput.incomingMessagesHash; // 5. Execute afterBlock hooks - this.assertSTProofInput(stateTransitionProof, state.stateRoot); + // this.assertSTProofInput(stateTransitionProof, state.stateRoot); const afterBlockResult = await this.executeBlockHooks( state, @@ -603,15 +607,15 @@ export class BlockProverProgrammable extends ZkProgrammable< state.networkStateHash = afterBlockResult.networkState.hash(); // We are reusing runtime STs here as afterBlock STs - stateTransitionProof.publicInput.stateTransitionsHash.assertEquals( - afterBlockHashList.commitment, - "STProof from-ST-hash not matching generated ST-hash from afterBlock hooks" - ); - state.stateRoot = Provable.if( - stsEmitted, - stateTransitionProof.publicOutput.stateRoot, - state.stateRoot - ); + // stateTransitionProof.publicInput.protocolTransitionsHash.assertEquals( + // afterBlockHashList.commitment, + // "STProof from-ST-hash not matching generated ST-hash from afterBlock hooks" + // ); + // state.stateRoot = Provable.if( + // stsEmitted, + // stateTransitionProof.publicOutput.stateRoot, + // state.stateRoot + // ); // 6. Close block @@ -791,7 +795,6 @@ export class BlockProverProgrammable extends ZkProgrammable< >[] { const { prover, stateTransitionProver } = this; const StateTransitionProofClass = stateTransitionProver.zkProgram[0].Proof; - const RuntimeProofClass = DynamicRuntimeProof; const proveTransaction = prover.proveTransaction.bind(prover); const proveBlock = prover.proveBlock.bind(prover); const merge = prover.merge.bind(prover); @@ -805,7 +808,7 @@ export class BlockProverProgrammable extends ZkProgrammable< proveTransaction: { privateInputs: [ StateTransitionProofClass, - RuntimeProofClass, + DynamicRuntimeProof, BlockProverExecutionData, RuntimeVerificationKeyAttestation, ], @@ -831,21 +834,21 @@ export class BlockProverProgrammable extends ZkProgrammable< privateInputs: [ NetworkState, BlockHashMerkleTreeWitness, - StateTransitionProofClass, + // StateTransitionProofClass, SelfProof, ], async method( publicInput: BlockProverPublicInput, networkState: NetworkState, blockWitness: BlockHashMerkleTreeWitness, - stateTransitionProof: StateTransitionProof, + // stateTransitionProof: StateTransitionProof, transactionProof: BlockProverProof ) { return await proveBlock( publicInput, networkState, blockWitness, - stateTransitionProof, + // stateTransitionProof, transactionProof ); }, @@ -870,6 +873,7 @@ export class BlockProverProgrammable extends ZkProgrammable< const methods = { proveTransaction: program.proveTransaction, + proveBlock: program.proveBlock, merge: program.merge, }; @@ -941,14 +945,14 @@ export class BlockProver extends ProtocolModule implements BlockProvable { publicInput: BlockProverPublicInput, networkState: NetworkState, blockWitness: BlockHashMerkleTreeWitness, - stateTransitionProof: StateTransitionProof, + // stateTransitionProof: StateTransitionProof, transactionProof: BlockProverProof ): Promise { return this.zkProgrammable.proveBlock( publicInput, networkState, blockWitness, - stateTransitionProof, + // stateTransitionProof, transactionProof ); } diff --git a/packages/protocol/src/prover/statetransition/StateTransitionProver.ts b/packages/protocol/src/prover/statetransition/StateTransitionProver.ts index 51301625a..2ecf724a3 100644 --- a/packages/protocol/src/prover/statetransition/StateTransitionProver.ts +++ b/packages/protocol/src/prover/statetransition/StateTransitionProver.ts @@ -32,8 +32,19 @@ const errors = { propertyNotMatching: (property: string, step: string) => `${property} not matching ${step}`, - merkleWitnessNotCorrect: (index: number, type: string) => - `MerkleWitness not valid for StateTransition (${index}, type ${type})`, + merkleWitnessNotCorrect: ( + index: number, + type: ProvableStateTransitionType + ) => { + let s = `MerkleWitness not valid for StateTransition (${index}, type unknown)`; + Provable.asProver(() => { + s = s.replace( + "unknown", + type.isNormal().toBoolean() ? "normal" : "protocol" + ); + }); + return s; + }, noWitnessProviderSet: () => new Error( @@ -67,8 +78,8 @@ export class StateTransitionProverProgrammable extends ZkProgrammable< super(); } - public get appChain(): AreProofsEnabled | undefined { - return this.stateTransitionProver.appChain; + public get areProofsEnabled(): AreProofsEnabled | undefined { + return this.stateTransitionProver.areProofsEnabled; } public zkProgramFactory(): PlainZkProgram< @@ -83,7 +94,7 @@ export class StateTransitionProverProgrammable extends ZkProgrammable< publicOutput: StateTransitionProverPublicOutput, methods: { - proveBatch: { + runBatch: { privateInputs: [StateTransitionProvableBatch], async method( @@ -112,7 +123,7 @@ export class StateTransitionProverProgrammable extends ZkProgrammable< }); const methods = { - proveBatch: program.proveBatch.bind(program), + runBatch: program.runBatch.bind(program), merge: program.merge.bind(program), }; @@ -194,12 +205,7 @@ export class StateTransitionProverProgrammable extends ZkProgrammable< membershipValid .or(transition.from.isSome.not()) - .assertTrue( - errors.merkleWitnessNotCorrect( - index, - type.isNormal().toBoolean() ? "normal" : "protocol" - ) - ); + .assertTrue(errors.merkleWitnessNotCorrect(index, type)); const newRoot = merkleWitness.calculateRoot(transition.to.value); diff --git a/packages/protocol/src/settlement/SettlementContractModule.ts b/packages/protocol/src/settlement/SettlementContractModule.ts index dc639013f..d832f2cb6 100644 --- a/packages/protocol/src/settlement/SettlementContractModule.ts +++ b/packages/protocol/src/settlement/SettlementContractModule.ts @@ -94,7 +94,7 @@ export class SettlementContractModule< // ** For protocol module public protocol?: ProtocolEnvironment; - public get appChain(): AreProofsEnabled | undefined { + public get areProofsEnabled(): AreProofsEnabled | undefined { return this.protocol?.getAreProofsEnabled(); } // ** diff --git a/packages/protocol/test/BlockProver.test.ts b/packages/protocol/test/BlockProver.test.ts index b02dd6909..ef8cff7ca 100644 --- a/packages/protocol/test/BlockProver.test.ts +++ b/packages/protocol/test/BlockProver.test.ts @@ -34,7 +34,7 @@ class RuntimeZkProgrammable extends ZkProgrammable< undefined, MethodPublicOutput > { - get appChain(): AreProofsEnabled | undefined { + get areProofsEnabled(): AreProofsEnabled | undefined { return new MockAppChain(); } diff --git a/packages/sdk/src/appChain/AppChain.ts b/packages/sdk/src/appChain/AppChain.ts index d19aa71b1..47761f6a8 100644 --- a/packages/sdk/src/appChain/AppChain.ts +++ b/packages/sdk/src/appChain/AppChain.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/consistent-type-assertions */ import { + AreProofsEnabled, ModuleContainer, ModulesConfig, ModulesRecord, @@ -304,12 +305,19 @@ export class AppChain< /** * Starts the appchain and cross-registers runtime to sequencer */ - public async start(dependencyContainer: DependencyContainer = container) { + public async start( + proofsEnabled: boolean = false, + dependencyContainer: DependencyContainer = container + ) { this.create(() => dependencyContainer); this.useDependencyFactory(this.container.resolve(AreProofsEnabledFactory)); this.useDependencyFactory(this.container.resolve(SharedDependencyFactory)); + this.container + .resolve("AreProofsEnabled") + .setProofsEnabled(proofsEnabled); + // These three statements are crucial for dependencies inside any of these // components to access their siblings inside their constructor. // This is because when it is the first time they are resolved, create() diff --git a/packages/sequencer/src/helpers/utils.ts b/packages/sequencer/src/helpers/utils.ts index 2921a7037..0186395a7 100644 --- a/packages/sequencer/src/helpers/utils.ts +++ b/packages/sequencer/src/helpers/utils.ts @@ -57,7 +57,7 @@ abstract class ProofTaskSerializerBase { return new c({ publicInput, publicOutput, - proof: "mock-proof", + proof: MOCK_PROOF, maxProofsVerified: jsonProof.maxProofsVerified, }); } @@ -119,7 +119,7 @@ export class ProofTaskSerializer public async fromJSONProof( jsonProof: JsonProof ): Promise> { - if (jsonProof.proof === "mock-proof") { + if (jsonProof.proof === MOCK_PROOF) { return this.getDummy(this.proofClass, jsonProof); } @@ -149,7 +149,7 @@ export class DynamicProofTaskSerializer public async fromJSONProof( jsonProof: JsonProof ): Promise> { - if (jsonProof.proof === "mock-proof") { + if (jsonProof.proof === MOCK_PROOF) { return this.getDummy(this.proofClass, jsonProof); } diff --git a/packages/sequencer/src/index.ts b/packages/sequencer/src/index.ts index 85c8faf55..4eb8fffa3 100644 --- a/packages/sequencer/src/index.ts +++ b/packages/sequencer/src/index.ts @@ -21,7 +21,7 @@ export * from "./protocol/baselayer/NoopBaseLayer"; export * from "./protocol/production/helpers/UntypedOption"; export * from "./protocol/production/helpers/UntypedStateTransition"; export * from "./protocol/production/tasks/BlockProvingTask"; -export * from "./protocol/production/tasks/CompileRegistry"; +export * from "./protocol/production/helpers/CompileRegistry"; export * from "./protocol/production/tasks/RuntimeProvingTask"; export * from "./protocol/production/tasks/RuntimeTaskParameters"; export * from "./protocol/production/tasks/StateTransitionTask"; @@ -36,7 +36,7 @@ export * from "./protocol/production/TransactionTraceService"; export * from "./protocol/production/sequencing/TransactionExecutionService"; export * from "./protocol/production/sequencing/BlockProducerModule"; export * from "./protocol/production/flow/ReductionTaskFlow"; -export * from "./protocol/ProtocolStartupModule"; +export * from "./sequencer/SequencerStartupModule"; export * from "./storage/model/Batch"; export * from "./storage/model/Block"; export * from "./storage/model/Settlement"; diff --git a/packages/sequencer/src/protocol/production/BlockTaskFlowService.ts b/packages/sequencer/src/protocol/production/BlockTaskFlowService.ts index 336d9cdba..c369dc8b5 100644 --- a/packages/sequencer/src/protocol/production/BlockTaskFlowService.ts +++ b/packages/sequencer/src/protocol/production/BlockTaskFlowService.ts @@ -9,7 +9,7 @@ import { Protocol, StateTransitionProof, } from "@proto-kit/protocol"; -import { log, MAX_FIELD, MOCK_PROOF } from "@proto-kit/common"; +import { log, MAX_FIELD } from "@proto-kit/common"; import { TaskQueue } from "../../worker/queue/TaskQueue"; import { Flow, FlowCreator } from "../../worker/flow/Flow"; @@ -274,6 +274,8 @@ export class BlockTaskFlowService { } ); + // TODO Dummy ST Proof for transactions that don't emit STs + const stReductionFlow = this.createSTMergeFlow( `tx-stproof-${batchId}-${blockNumber}-${transactionIndex}`, trace.stateTransitionProver.length @@ -319,12 +321,12 @@ export class BlockTaskFlowService { // Provide a dummy prove is this block is empty const proof = - new this.protocol.blockProver.zkProgrammable.zkProgram[0].Proof({ + await this.protocol.blockProver.zkProgrammable.zkProgram[0].Proof.dummy( publicInput, publicOutput, - proof: MOCK_PROOF, - maxProofsVerified: 2, - }); + 2 + ); + flow.state.blockPairings[blockNumber].blockProof = proof; await this.pushBlockPairing(flow, blockMergingFlow, blockNumber); } @@ -335,14 +337,12 @@ export class BlockTaskFlowService { const [{ publicInput }] = blockTrace.stateTransitionProver; flow.state.blockPairings[blockNumber].stProof = - new this.protocol.stateTransitionProver.zkProgrammable.zkProgram[0].Proof( - { - publicInput, - proof: MOCK_PROOF, - publicOutput: publicInput, - maxProofsVerified: 2, - } + await this.protocol.stateTransitionProver.zkProgrammable.zkProgram[0].Proof.dummy( + publicInput, + publicInput, + 2 ); + await this.pushBlockPairing(flow, blockMergingFlow, blockNumber); } else { const blockSTFlow = this.createSTMergeFlow( diff --git a/packages/sequencer/src/protocol/production/TransactionTraceService.ts b/packages/sequencer/src/protocol/production/TransactionTraceService.ts index 0ccb5c136..11876fbcd 100644 --- a/packages/sequencer/src/protocol/production/TransactionTraceService.ts +++ b/packages/sequencer/src/protocol/production/TransactionTraceService.ts @@ -97,8 +97,8 @@ export class TransactionTraceService { ({ stParameters, fromStateRoot } = await this.createMerkleTrace( stateServices.merkleStore, - stateTransitions, [], + stateTransitions, true )); } else { diff --git a/packages/sequencer/src/protocol/production/tasks/CompileRegistry.ts b/packages/sequencer/src/protocol/production/helpers/CompileRegistry.ts similarity index 72% rename from packages/sequencer/src/protocol/production/tasks/CompileRegistry.ts rename to packages/sequencer/src/protocol/production/helpers/CompileRegistry.ts index 4fb910deb..8c4d8a09f 100644 --- a/packages/sequencer/src/protocol/production/tasks/CompileRegistry.ts +++ b/packages/sequencer/src/protocol/production/helpers/CompileRegistry.ts @@ -21,11 +21,12 @@ export class CompileRegistry { zkProgram: { compile: () => Promise } ) { if (this.compilationPromises[name] === undefined) { - log.info(`Compiling ${name}`); + log.time(`Compiling ${name}`); this.compilationPromises[name] = zkProgram.compile(); + log.timeEnd.info(`Compiling ${name}`); } - await this.compilationPromises[name]; - log.info(`Compiled ${name}`); + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + return (await this.compilationPromises[name]) as CompileArtifact; } public async compileSmartContract( @@ -37,11 +38,14 @@ export class CompileRegistry { ) { if (this.compilationPromises[name] === undefined) { if (proofsEnabled) { + log.time(`Compiling ${name}`); this.compilationPromises[name] = contract.compile(); + log.timeEnd.info(`Compiling ${name}`); } else { this.compilationPromises[name] = Promise.resolve({}); } } - await this.compilationPromises[name]; + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + return (await this.compilationPromises[name]) as ContractCompileArtifact; } } diff --git a/packages/sequencer/src/protocol/production/helpers/VerificationKeySerializer.ts b/packages/sequencer/src/protocol/production/helpers/VerificationKeySerializer.ts new file mode 100644 index 000000000..818b0cb94 --- /dev/null +++ b/packages/sequencer/src/protocol/production/helpers/VerificationKeySerializer.ts @@ -0,0 +1,19 @@ +import { Field, VerificationKey } from "o1js"; + +export type VerificationKeyJSON = { data: string; hash: string }; + +export class VerificationKeySerializer { + public static toJSON(verificationKey: VerificationKey): VerificationKeyJSON { + return { + data: verificationKey.data, + hash: verificationKey.hash.toJSON(), + }; + } + + public static fromJSON(json: VerificationKeyJSON): VerificationKey { + return new VerificationKey({ + data: json.data, + hash: Field.fromJSON(json.hash), + }); + } +} diff --git a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts index dae2a7b7a..841a956b6 100644 --- a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts @@ -138,11 +138,11 @@ export class TransactionExecutionService { if (module.runtime === undefined) { throw new Error("Runtime on RuntimeModule not set"); } - if (module.runtime.appChain === undefined) { + if (module.runtime.areProofsEnabled === undefined) { throw new Error("AppChain on Runtime not set"); } - const { appChain } = module.runtime; - return appChain; + const { areProofsEnabled } = module.runtime; + return areProofsEnabled; } private async executeWithExecutionContext( diff --git a/packages/sequencer/src/protocol/production/tasks/BlockProvingTask.ts b/packages/sequencer/src/protocol/production/tasks/BlockProvingTask.ts index 4861c6c77..7b09c6fc7 100644 --- a/packages/sequencer/src/protocol/production/tasks/BlockProvingTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/BlockProvingTask.ts @@ -18,10 +18,7 @@ import { import { Field, Proof } from "o1js"; import { Runtime } from "@proto-kit/module"; import { inject, injectable, Lifecycle, scoped } from "tsyringe"; -import { - MOCK_VERIFICATION_KEY, - ProvableMethodExecutionContext, -} from "@proto-kit/common"; +import { ProvableMethodExecutionContext } from "@proto-kit/common"; import { PairProofTaskSerializer, @@ -34,8 +31,9 @@ import { PreFilledStateService } from "../../../state/prefilled/PreFilledStateSe import { TaskWorkerModule } from "../../../worker/worker/TaskWorkerModule"; import { TaskStateRecord } from "../TransactionTraceService"; import { VerificationKeyService } from "../../runtime/RuntimeVerificationKeyService"; +import { VerificationKeySerializer } from "../helpers/VerificationKeySerializer"; +import { CompileRegistry } from "../helpers/CompileRegistry"; -import { CompileRegistry } from "./CompileRegistry"; import { JSONEncodableState } from "./RuntimeTaskParameters"; type RuntimeProof = Proof; @@ -73,6 +71,27 @@ export class DecodedStateSerializer { } } +class RuntimeVerificationKeyAttestationSerializer { + static fromJSON(json: { + verificationKey: { hash: string; data: string }; + witness: ReturnType; + }) { + return new RuntimeVerificationKeyAttestation({ + verificationKey: VerificationKeySerializer.fromJSON(json.verificationKey), + witness: new VKTreeWitness(VKTreeWitness.fromJSON(json.witness)), + }); + } + + static toJSON(attestation: RuntimeVerificationKeyAttestation) { + return { + verificationKey: VerificationKeySerializer.toJSON( + attestation.verificationKey + ), + witness: VKTreeWitness.toJSON(attestation.witness), + }; + } +} + @injectable() @scoped(Lifecycle.ContainerScoped) export class BlockReductionTask @@ -180,7 +199,7 @@ export class BlockProvingTask ), verificationKeyAttestation: - RuntimeVerificationKeyAttestation.toJSON( + RuntimeVerificationKeyAttestationSerializer.toJSON( input.params.verificationKeyAttestation ), }, @@ -198,7 +217,7 @@ export class BlockProvingTask executionData: ReturnType; startingState: JSONEncodableState; verificationKeyAttestation: ReturnType< - typeof RuntimeVerificationKeyAttestation.toJSON + typeof RuntimeVerificationKeyAttestationSerializer.toJSON >; }; } = JSON.parse(json); @@ -221,20 +240,9 @@ export class BlockProvingTask ), verificationKeyAttestation: - jsonReadyObject.params.verificationKeyAttestation - .verificationKey === MOCK_VERIFICATION_KEY.data - ? new RuntimeVerificationKeyAttestation({ - witness: new VKTreeWitness( - VKTreeWitness.fromJSON( - jsonReadyObject.params.verificationKeyAttestation - .witness - ) - ), - verificationKey: MOCK_VERIFICATION_KEY, - }) - : RuntimeVerificationKeyAttestation.fromJSON( - jsonReadyObject.params.verificationKeyAttestation - ), + RuntimeVerificationKeyAttestationSerializer.fromJSON( + jsonReadyObject.params.verificationKeyAttestation + ), }, }; }, @@ -252,7 +260,9 @@ export class BlockProvingTask startingState: TaskStateRecord, callback: () => Promise ): Promise { - const prefilledStateService = new PreFilledStateService(startingState); + const prefilledStateService = new PreFilledStateService({ + ...startingState, + }); this.stateServiceProvider.setCurrentStateService(prefilledStateService); const returnValue = await callback(); diff --git a/packages/sequencer/src/protocol/production/tasks/CircuitCompilerTask.ts b/packages/sequencer/src/protocol/production/tasks/CircuitCompilerTask.ts index 1adeee6dc..d63a9e083 100644 --- a/packages/sequencer/src/protocol/production/tasks/CircuitCompilerTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/CircuitCompilerTask.ts @@ -1,18 +1,29 @@ import { inject, injectable, Lifecycle, scoped } from "tsyringe"; import { Runtime } from "@proto-kit/module"; -import { Field, VerificationKey } from "o1js"; -import { log } from "@proto-kit/common"; +import { VerificationKey } from "o1js"; +import { log, mapSequential } from "@proto-kit/common"; +import { + MandatorySettlementModulesRecord, + NetworkState, + Protocol, + RuntimeMethodExecutionContext, + RuntimeTransaction, + SettlementContractModule, +} from "@proto-kit/protocol"; import { TaskSerializer } from "../../../worker/flow/Task"; import { VKRecord } from "../../runtime/RuntimeVerificationKeyService"; import { UnpreparingTask } from "../../../worker/flow/UnpreparingTask"; +import { VerificationKeySerializer } from "../helpers/VerificationKeySerializer"; -type VKRecordLite = Record< - string, - { vk: { hash: string; data: string }; index: string } ->; +export type CompiledCircuitsRecord = { + protocolCircuits: VKRecord; + runtimeCircuits: VKRecord; +}; -export class DefaultSerializer implements TaskSerializer { +type VKRecordLite = Record; + +export class UndefinedSerializer implements TaskSerializer { public toJSON(parameters: undefined): string { return ""; } @@ -22,38 +33,28 @@ export class DefaultSerializer implements TaskSerializer { } } -export class VKResultSerializer implements TaskSerializer { - public toJSON(input: VKRecord): string { +export class VKResultSerializer { + public toJSON(input: VKRecord): VKRecordLite { const temp: VKRecordLite = Object.keys(input).reduce( (accum, key) => { return { ...accum, [key]: { - vk: { - hash: input[key].vk.hash.toString(), - data: input[key].vk.data, - }, - index: input[key].index.toString(), + vk: VerificationKeySerializer.toJSON(input[key].vk), }, }; }, {} ); - return JSON.stringify(temp); + return temp; } - public fromJSON(json: string): VKRecord { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const temp: VKRecordLite = JSON.parse(json); - return Object.keys(temp).reduce((accum, key) => { + public fromJSON(json: VKRecordLite): VKRecord { + return Object.keys(json).reduce((accum, key) => { return { ...accum, [key]: { - vk: new VerificationKey({ - data: temp[key].vk.data, - hash: Field(temp[key].vk.hash), - }), - index: BigInt(temp[key].index), + vk: VerificationKeySerializer.fromJSON(json[key].vk), }, }; }, {}); @@ -62,56 +63,122 @@ export class VKResultSerializer implements TaskSerializer { @injectable() @scoped(Lifecycle.ContainerScoped) -export class CircuitCompilerTask extends UnpreparingTask { +export class CircuitCompilerTask extends UnpreparingTask< + undefined, + CompiledCircuitsRecord +> { public name = "compiledCircuit"; public constructor( - @inject("Runtime") protected readonly runtime: Runtime + @inject("Runtime") protected readonly runtime: Runtime, + @inject("Protocol") protected readonly protocol: Protocol ) { super(); } public inputSerializer(): TaskSerializer { - return new DefaultSerializer(); + return new UndefinedSerializer(); } - public resultSerializer(): TaskSerializer { - return new VKResultSerializer(); + public resultSerializer(): TaskSerializer { + const vkRecordSerializer = new VKResultSerializer(); + return { + fromJSON: (json) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const temp: { + runtimeCircuits: VKRecordLite; + protocolCircuits: VKRecordLite; + } = JSON.parse(json); + return { + runtimeCircuits: vkRecordSerializer.fromJSON(temp.runtimeCircuits), + protocolCircuits: vkRecordSerializer.fromJSON(temp.protocolCircuits), + }; + }, + toJSON: (input) => { + return JSON.stringify({ + runtimeCircuits: vkRecordSerializer.toJSON(input.runtimeCircuits), + protocolCircuits: vkRecordSerializer.toJSON(input.protocolCircuits), + }); + }, + }; } - public async compute(): Promise { - log.info("Computing VKs"); + public async compileRuntimeMethods() { + log.time("Compiling runtime circuits"); - let methodCounter = 0; - return await this.runtime.zkProgrammable.zkProgram.reduce< - Promise - >(async (accum, program) => { - const vk = (await program.compile()).verificationKey; + const context = this.runtime.dependencyContainer.resolve( + RuntimeMethodExecutionContext + ); + context.setup({ + transaction: RuntimeTransaction.dummyTransaction(), + networkState: NetworkState.empty(), + }); - const vkRecordStep = Object.keys(program.methods).reduce( - (previousRecord, combinedMethodName) => { + const result = await mapSequential( + this.runtime.zkProgrammable.zkProgram, + async (program) => { + const vk = (await program.compile()).verificationKey; + + return Object.keys(program.methods).map((combinedMethodName) => { const [moduleName, methodName] = combinedMethodName.split("."); const methodId = this.runtime.methodIdResolver.getMethodId( moduleName, methodName ); - return { - ...previousRecord, - [methodId.toString()]: { - vk, - // eslint-disable-next-line no-plusplus - index: BigInt(methodCounter++), - }, - }; - }, - {} - ); + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + return [methodId.toString(), new VerificationKey(vk)] as [ + string, + VerificationKey, + ]; + }); + } + ); + log.timeEnd.info("Compiling runtime circuits"); + return result; + } - const vkRecord = await accum; - return { - ...vkRecord, - ...vkRecordStep, - }; - }, Promise.resolve({})); + public async compileProtocolCircuits(): Promise< + [string, VerificationKey][][] + > { + // We only care about the BridgeContract for now - later with cachine, + // we might want to expand that to all protocol circuits + const container = this.protocol.dependencyContainer; + if (container.isRegistered("SettlementContractModule")) { + log.time("Compiling protocol circuits"); + + const settlementModule = container.resolve< + SettlementContractModule + >("SettlementContractModule"); + + const BridgeClass = settlementModule.getContractClasses().bridge; + const artifact = await BridgeClass.compile(); + + log.timeEnd.info("Compiling protocol circuits"); + + return [[["BridgeContract", artifact.verificationKey]]]; + } + return [[]]; + } + + public collectRecord(tuples: [string, VerificationKey][][]): VKRecord { + return tuples.flat().reduce((acc, step) => { + acc[step[0]] = { vk: step[1] }; + return acc; + }, {}); + } + + public async compute(): Promise { + log.info("Computing VKs"); + + const runtimeTuples = await this.compileRuntimeMethods(); + const runtimeRecord = this.collectRecord(runtimeTuples); + + const protocolTuples = await this.compileProtocolCircuits(); + const protocolRecord = this.collectRecord(protocolTuples); + + return { + runtimeCircuits: runtimeRecord, + protocolCircuits: protocolRecord, + }; } } diff --git a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts index ddb643fbc..d29638559 100644 --- a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts @@ -20,9 +20,9 @@ import { PreFilledStateService } from "../../../state/prefilled/PreFilledStateSe import { TaskWorkerModule } from "../../../worker/worker/TaskWorkerModule"; import { PairingDerivedInput } from "../flow/ReductionTaskFlow"; import { TaskStateRecord } from "../TransactionTraceService"; +import { CompileRegistry } from "../helpers/CompileRegistry"; import { JSONEncodableState } from "./RuntimeTaskParameters"; -import { CompileRegistry } from "./CompileRegistry"; import { DecodedStateSerializer } from "./BlockProvingTask"; type BlockProof = Proof; @@ -147,7 +147,9 @@ export class NewBlockTask startingState: TaskStateRecord, callback: () => Promise ): Promise { - const prefilledStateService = new PreFilledStateService(startingState); + const prefilledStateService = new PreFilledStateService({ + ...startingState, + }); this.protocol.stateServiceProvider.setCurrentStateService( prefilledStateService ); @@ -160,7 +162,9 @@ export class NewBlockTask } public async compute(input: NewBlockProvingParameters): Promise { - const { input1, input2, params: parameters } = input; + // TODO I left the task arg for the ST Proof in, until it will be reworked + // with the new ST Prover + const { input2, params: parameters } = input; const { networkState, blockWitness, startingState, publicInput } = parameters; @@ -169,7 +173,7 @@ export class NewBlockTask publicInput, networkState, blockWitness, - input1, + // input1, input2 ); }); diff --git a/packages/sequencer/src/protocol/production/tasks/StateTransitionTask.ts b/packages/sequencer/src/protocol/production/tasks/StateTransitionTask.ts index e3631581d..a3cd86e8e 100644 --- a/packages/sequencer/src/protocol/production/tasks/StateTransitionTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/StateTransitionTask.ts @@ -18,12 +18,12 @@ import { ProofTaskSerializer, } from "../../../helpers/utils"; import { TaskWorkerModule } from "../../../worker/worker/TaskWorkerModule"; +import { CompileRegistry } from "../helpers/CompileRegistry"; import { StateTransitionParametersSerializer, StateTransitionProofParameters, } from "./StateTransitionTaskParameters"; -import { CompileRegistry } from "./CompileRegistry"; @injectable() @scoped(Lifecycle.ContainerScoped) diff --git a/packages/sequencer/src/protocol/runtime/RuntimeVerificationKeyService.ts b/packages/sequencer/src/protocol/runtime/RuntimeVerificationKeyService.ts index fb52db301..43d722e79 100644 --- a/packages/sequencer/src/protocol/runtime/RuntimeVerificationKeyService.ts +++ b/packages/sequencer/src/protocol/runtime/RuntimeVerificationKeyService.ts @@ -19,7 +19,6 @@ export interface VKIndexes { export type VKRecord = { [methodId: string]: { vk: VerificationKey; - index: bigint; }; }; @@ -59,15 +58,18 @@ export class VerificationKeyService extends ConfigurableModule<{}> { const valuesVK: Record = {}; const indexes: VKIndexes = {}; - Object.entries(verificationKeys).forEach(([key, value]) => { - const vkConfig = new MethodVKConfigData({ - methodId: Field(key), - vkHash: Field(value.vk.hash), + Object.entries(verificationKeys) + // eslint-disable-next-line no-nested-ternary + .sort(([key], [key2]) => (key > key2 ? 1 : key === key2 ? 0 : -1)) + .forEach(([key, value], index) => { + const vkConfig = new MethodVKConfigData({ + methodId: Field(key), + vkHash: Field(value.vk.hash), + }); + indexes[key] = BigInt(index); + tree.setLeaf(BigInt(index), vkConfig.hash()); + valuesVK[key.toString()] = value.vk; }); - indexes[key] = BigInt(value.index); - tree.setLeaf(BigInt(value.index), vkConfig.hash()); - valuesVK[key.toString()] = value.vk; - }); this.persistedVKTree = { tree, indexes }; this.persistedVKRecord = valuesVK; diff --git a/packages/sequencer/src/protocol/ProtocolStartupModule.ts b/packages/sequencer/src/sequencer/SequencerStartupModule.ts similarity index 51% rename from packages/sequencer/src/protocol/ProtocolStartupModule.ts rename to packages/sequencer/src/sequencer/SequencerStartupModule.ts index 48df481e8..402e12ad4 100644 --- a/packages/sequencer/src/protocol/ProtocolStartupModule.ts +++ b/packages/sequencer/src/sequencer/SequencerStartupModule.ts @@ -3,24 +3,22 @@ import { MandatoryProtocolModulesRecord, Protocol, RuntimeVerificationKeyRootService, + SettlementSmartContractBase, } from "@proto-kit/protocol"; -import { log, sleep } from "@proto-kit/common"; +import { log } from "@proto-kit/common"; -import { - SequencerModule, - sequencerModule, -} from "../sequencer/builder/SequencerModule"; import { FlowCreator } from "../worker/flow/Flow"; -import { WorkerRegistrationFlow } from "../worker/WorkerRegistrationFlow"; - -import { CircuitCompilerTask } from "./production/tasks/CircuitCompilerTask"; +import { WorkerRegistrationFlow } from "../worker/worker/startup/WorkerRegistrationFlow"; import { - VerificationKeyService, - VKRecord, -} from "./runtime/RuntimeVerificationKeyService"; + CircuitCompilerTask, + CompiledCircuitsRecord, +} from "../protocol/production/tasks/CircuitCompilerTask"; +import { VerificationKeyService } from "../protocol/runtime/RuntimeVerificationKeyService"; + +import { SequencerModule, sequencerModule } from "./builder/SequencerModule"; @sequencerModule() -export class ProtocolStartupModule extends SequencerModule { +export class SequencerStartupModule extends SequencerModule { public constructor( private readonly flowCreator: FlowCreator, @inject("Protocol") @@ -37,15 +35,18 @@ export class ProtocolStartupModule extends SequencerModule { log.info("Compiling Protocol circuits, this can take a few minutes"); - const vks = await flow.withFlow(async (res, rej) => { - await flow.pushTask(this.compileTask, undefined, async (result) => { - res(result); - }); - }); + const vks = await flow.withFlow( + async (res, rej) => { + await flow.pushTask(this.compileTask, undefined, async (result) => { + res(result); + }); + } + ); log.info("Protocol circuits compiled"); - await this.verificationKeyService.initializeVKTree(vks); + // Init runtime VK tree + await this.verificationKeyService.initializeVKTree(vks.runtimeCircuits); const root = this.verificationKeyService.getRoot(); @@ -53,12 +54,18 @@ export class ProtocolStartupModule extends SequencerModule { .resolve(RuntimeVerificationKeyRootService) .setRoot(root); + // Init BridgeContract vk for settlement contract + const bridgeVk = vks.protocolCircuits.BridgeContract; + if (bridgeVk !== undefined) { + SettlementSmartContractBase.args.BridgeContractVerificationKey = + bridgeVk.vk; + } + await this.registrationFlow.start({ runtimeVerificationKeyRoot: root, + bridgeContractVerificationKey: bridgeVk?.vk, }); - await sleep(500); - log.info("Protocol circuits compiled successfully, commencing startup"); } } diff --git a/packages/sequencer/src/settlement/SettlementModule.ts b/packages/sequencer/src/settlement/SettlementModule.ts index be06a0ab1..6484bcfdd 100644 --- a/packages/sequencer/src/settlement/SettlementModule.ts +++ b/packages/sequencer/src/settlement/SettlementModule.ts @@ -26,7 +26,6 @@ import { log, AreProofsEnabled, DependencyFactory, - MOCK_VERIFICATION_KEY, } from "@proto-kit/common"; import truncate from "lodash/truncate"; @@ -379,7 +378,7 @@ export class SettlementModule public async start(): Promise { const contractArgs = SettlementSmartContractBase.args; - const dummyVk = MOCK_VERIFICATION_KEY; + // const dummyVk = MOCK_VERIFICATION_KEY; SettlementSmartContractBase.args = { ...contractArgs, @@ -389,9 +388,9 @@ export class SettlementModule ? new SignedSettlementPermissions() : new ProvenSettlementPermissions() ).bridgeContractMina(), - BridgeContractVerificationKey: this.utils.isSignedSettlement() - ? undefined - : dummyVk, + // BridgeContractVerificationKey: this.utils.isSignedSettlement() + // ? undefined + // : dummyVk, }; // TODO Add task to compute verification key diff --git a/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts b/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts index 78747633d..95cda66a3 100644 --- a/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts +++ b/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts @@ -30,7 +30,7 @@ import { ProofTaskSerializer, DynamicProofTaskSerializer, } from "../../helpers/utils"; -import { CompileRegistry } from "../../protocol/production/tasks/CompileRegistry"; +import { CompileRegistry } from "../../protocol/production/helpers/CompileRegistry"; import { Task, TaskSerializer } from "../../worker/flow/Task"; import { TaskWorkerModule } from "../../worker/worker/TaskWorkerModule"; diff --git a/packages/sequencer/src/worker/queue/LocalTaskQueue.ts b/packages/sequencer/src/worker/queue/LocalTaskQueue.ts index 39a63d673..57725b4f8 100644 --- a/packages/sequencer/src/worker/queue/LocalTaskQueue.ts +++ b/packages/sequencer/src/worker/queue/LocalTaskQueue.ts @@ -1,4 +1,4 @@ -import { log, noop } from "@proto-kit/common"; +import { log, mapSequential, noop } from "@proto-kit/common"; import { SequencerModule } from "../../sequencer/builder/SequencerModule"; import { TaskPayload } from "../flow/Task"; @@ -42,32 +42,54 @@ export class LocalTaskQueue [key: string]: QueueListener[] | undefined; } = {}; - public workNextTasks() { - Object.entries(this.queues).forEach(([queueName, tasks]) => { - if (tasks.length > 0 && this.workers[queueName]) { - tasks.forEach((task) => { - // Execute task in worker - - void this.workers[queueName] - ?.handler(task.payload) - .then((payload) => { - if (payload === "closed") { - return; + private taskInProgress = false; + + public async workNextTasks() { + if (this.taskInProgress) { + return; + } + this.taskInProgress = true; + + // Collect all tasks + const tasksToExecute = Object.entries(this.queues).flatMap( + ([queueName, tasks]) => { + if (tasks.length > 0 && this.workers[queueName]) { + const functions = tasks.map((task) => async () => { + // Execute task in worker + + const payload = await this.workers[queueName]?.handler( + task.payload + ); + + if (payload === "closed" || payload === undefined) { + return; + } + log.trace("LocalTaskQueue got", JSON.stringify(payload)); + // Notify listeners about result + const listenerPromises = this.listeners[queueName]?.map( + async (listener) => { + await listener(payload); } - log.trace("LocalTaskQueue got", JSON.stringify(payload)); - // Notify listeners about result - const listenerPromises = this.listeners[queueName]?.map( - async (listener) => { - await listener(payload); - } - ); - void Promise.all(listenerPromises || []); - }); - }); + ); + void Promise.all(listenerPromises || []); + }); + this.queues[queueName] = []; + return functions; + } + + return []; } + ); + + // Execute all tasks + await mapSequential(tasksToExecute, async (task) => await task()); + + this.taskInProgress = false; - this.queues[queueName] = []; - }); + // In case new tasks came up in the meantime, execute them as well + if (tasksToExecute.length > 0) { + await this.workNextTasks(); + } } public createWorker( @@ -105,7 +127,7 @@ export class LocalTaskQueue }; this.workers[queueName] = worker; - this.workNextTasks(); + void this.workNextTasks(); return worker; } @@ -126,7 +148,7 @@ export class LocalTaskQueue const nextId = taskId ?? String(id).toString(); this.queues[queueName].push({ payload, taskId: nextId }); - this.workNextTasks(); + void this.workNextTasks(); return { taskId: nextId }; }, diff --git a/packages/sequencer/src/worker/worker/FlowTaskWorker.ts b/packages/sequencer/src/worker/worker/FlowTaskWorker.ts index 39f308db0..704bd5e44 100644 --- a/packages/sequencer/src/worker/worker/FlowTaskWorker.ts +++ b/packages/sequencer/src/worker/worker/FlowTaskWorker.ts @@ -28,10 +28,10 @@ export class FlowTaskWorker[]> // The array type is this weird, because we first want to extract the // element type, and after that, we expect multiple elements of that -> [] private initHandler(task: Task) { - log.debug(`Init task ${task.name}`); + log.debug(`Init task handler ${task.name}`); const queueName = task.name; return this.queue.createWorker(queueName, async (data) => { - log.debug(`Received task in queue ${queueName}`); + log.debug(`Received task ${data.taskId} in queue ${queueName}`); try { // Use first handler that returns a non-undefined result @@ -51,12 +51,16 @@ export class FlowTaskWorker[]> payload: await task.resultSerializer().toJSON(output), }; + log.debug( + `Responding to task ${data.taskId} with ${result.payload.slice(0, 100)}` + ); + return result; } catch (error: unknown) { const payload = error instanceof Error ? error.message : JSON.stringify(error); - log.debug("Error in worker (detailed trace): ", error); + log.info("Error in worker (detailed trace): ", error); return { status: "error", @@ -69,6 +73,14 @@ export class FlowTaskWorker[]> }); } + preparePromise?: Promise; + + prepareResolve?: () => void; + + public waitForPrepared(): Promise { + return this.preparePromise!; + } + public async prepareTasks(tasks: Task[]) { log.info("Preparing tasks..."); @@ -76,6 +88,7 @@ export class FlowTaskWorker[]> // Call them in order of registration, because the prepare methods // might depend on each other or a result that is saved in a DI singleton for (const task of tasks) { + log.debug(`Preparing task ${task.constructor.name}`); // eslint-disable-next-line no-await-in-loop await task.prepare(); } @@ -89,6 +102,8 @@ export class FlowTaskWorker[]> ...this.workers, ...newWorkers, }; + + this.prepareResolve!(); } public async start() { @@ -114,6 +129,11 @@ export class FlowTaskWorker[]> (task) => !isUnpreparingTask(task) && !isAbstractStartupTask(task) ); + const preparePromise = new Promise((res) => { + this.prepareResolve = res; + }); + this.preparePromise = preparePromise; + if (startupTasks.length > 0) { this.workers = Object.fromEntries( unpreparingTasks diff --git a/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts b/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts index 5609e718a..46c545482 100644 --- a/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts +++ b/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts @@ -1,4 +1,6 @@ import { + EventEmitter, + EventEmittingContainer, log, ModuleContainer, ModulesConfig, @@ -42,6 +44,8 @@ export type TaskWorkerModulesRecord = ModulesRecord< TypedClass> >; +type LocalTaskWorkerModuleEvents = { ready: [boolean] }; + /** * This module spins up a worker in the current local node instance. * This should only be used for local testing/development and not in a @@ -51,10 +55,14 @@ export type TaskWorkerModulesRecord = ModulesRecord< @sequencerModule() export class LocalTaskWorkerModule extends ModuleContainer - implements SequencerModule + implements + SequencerModule, + EventEmittingContainer { public static presets: Presets = {}; + public containerEvents = new EventEmitter(); + public static from( modules: Tasks ): TypedClass> { @@ -90,12 +98,21 @@ export class LocalTaskWorkerModule this.assertIsValidModuleName(moduleName); const task = this.resolve(moduleName); - log.info(`Resolved task ${task.name}`); + log.debug(`Resolved task ${task.name}`); return task; }); const worker = new FlowTaskWorker(this.taskQueue(), [...tasks]); await worker.start(); + + void worker + .waitForPrepared() + .then(() => { + this.containerEvents.emit("ready", true); + }) + .catch((e) => { + log.error("Error occurring waiting for the ready event", e); + }); } } diff --git a/packages/sequencer/src/worker/WorkerRegistrationFlow.ts b/packages/sequencer/src/worker/worker/startup/WorkerRegistrationFlow.ts similarity index 81% rename from packages/sequencer/src/worker/WorkerRegistrationFlow.ts rename to packages/sequencer/src/worker/worker/startup/WorkerRegistrationFlow.ts index 954099897..17108ff0f 100644 --- a/packages/sequencer/src/worker/WorkerRegistrationFlow.ts +++ b/packages/sequencer/src/worker/worker/startup/WorkerRegistrationFlow.ts @@ -1,12 +1,13 @@ import { injectable } from "tsyringe"; import { log } from "@proto-kit/common"; -import { Closeable } from "./queue/TaskQueue"; -import { FlowCreator } from "./flow/Flow"; +import { Closeable } from "../../queue/TaskQueue"; +import { FlowCreator } from "../../flow/Flow"; + import { WorkerRegistrationTask, WorkerStartupPayload, -} from "./worker/startup/WorkerRegistrationTask"; +} from "./WorkerRegistrationTask"; @injectable() export class WorkerRegistrationFlow implements Closeable { @@ -17,7 +18,9 @@ export class WorkerRegistrationFlow implements Closeable { flow?: Closeable; - public async start(payload: WorkerStartupPayload): Promise { + public async start( + payload: Omit + ): Promise { const flow = this.flowCreator.createFlow("register-worker-flow", {}); this.flow = flow; @@ -27,6 +30,7 @@ export class WorkerRegistrationFlow implements Closeable { // eslint-disable-next-line no-await-in-loop await flow.withFlow(async (res, rej) => { log.trace("Pushing registration task"); + await flow.pushTask(this.task, payload, async (result) => { // Here someone could inject things to happen when the worker registers res(result); diff --git a/packages/sequencer/src/worker/worker/startup/WorkerRegistrationTask.ts b/packages/sequencer/src/worker/worker/startup/WorkerRegistrationTask.ts index e08a7da99..f1cf74672 100644 --- a/packages/sequencer/src/worker/worker/startup/WorkerRegistrationTask.ts +++ b/packages/sequencer/src/worker/worker/startup/WorkerRegistrationTask.ts @@ -3,15 +3,20 @@ import { inject, injectable } from "tsyringe"; import { Protocol, RuntimeVerificationKeyRootService, + SettlementSmartContractBase, } from "@proto-kit/protocol"; +import { VerificationKey } from "o1js"; import { Task } from "../../flow/Task"; import { AbstractStartupTask } from "../../flow/AbstractStartupTask"; +import { VerificationKeySerializer } from "../../../protocol/production/helpers/VerificationKeySerializer"; import { CloseWorkerError } from "./CloseWorkerError"; export type WorkerStartupPayload = { runtimeVerificationKeyRoot: bigint; + // This has to be nullable, since + bridgeContractVerificationKey?: VerificationKey; }; @injectable() @@ -19,6 +24,7 @@ export class WorkerRegistrationTask extends AbstractStartupTask implements Task { + // Theoretically not needed anymore, but still nice as a safeguard against double execution private done = false; public constructor( @@ -44,6 +50,11 @@ export class WorkerRegistrationTask ); rootService.setRoot(input.runtimeVerificationKeyRoot); + if (input.bridgeContractVerificationKey !== undefined) { + SettlementSmartContractBase.args.BridgeContractVerificationKey = + input.bridgeContractVerificationKey; + } + this.events.emit("startup-task-finished"); this.done = true; @@ -56,6 +67,12 @@ export class WorkerRegistrationTask return JSON.stringify({ runtimeVerificationKeyRoot: payload.runtimeVerificationKeyRoot.toString(), + bridgeContractVerificationKey: + payload.bridgeContractVerificationKey !== undefined + ? VerificationKeySerializer.toJSON( + payload.bridgeContractVerificationKey + ) + : undefined, }); }, fromJSON: (payload: string) => { @@ -67,6 +84,13 @@ export class WorkerRegistrationTask // eslint-disable-next-line @typescript-eslint/no-unsafe-argument jsonObject.runtimeVerificationKeyRoot ), + bridgeContractVerificationKey: + jsonObject.bridgeContractVerificationKey !== undefined + ? VerificationKeySerializer.fromJSON( + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + jsonObject.bridgeContractVerificationKey + ) + : undefined, }; }, }; diff --git a/packages/sequencer/test-integration/workers/ChildProcessWorker.ts b/packages/sequencer/test-integration/workers/ChildProcessWorker.ts new file mode 100644 index 000000000..1e2614694 --- /dev/null +++ b/packages/sequencer/test-integration/workers/ChildProcessWorker.ts @@ -0,0 +1,31 @@ +import { spawn, ChildProcess } from "node:child_process"; + +export class ChildProcessWorker { + process?: ChildProcess; + + start(forwardLogs: boolean = true) { + const s = spawn("node", [ + "--experimental-vm-modules", + "--experimental-wasm-modules", + "../../node_modules/jest/bin/jest.js", + "./test-integration/workers/worker.test.ts", + ]); + s.on("error", (err) => { + console.error(err); + }); + if (forwardLogs) { + s.stdout.on("data", (data) => { + process.stdout.write(data); + }); + } + s.stderr.on("data", (data) => { + process.stderr.write(data); + }); + + this.process = s; + } + + kill() { + this?.process?.kill(); + } +} diff --git a/packages/sequencer/test-integration/workers/WorkerModules.ts b/packages/sequencer/test-integration/workers/WorkerModules.ts new file mode 100644 index 000000000..e1d640aa3 --- /dev/null +++ b/packages/sequencer/test-integration/workers/WorkerModules.ts @@ -0,0 +1,6 @@ +import { LocalTaskWorkerModule, TaskQueue, TypedClass } from "../../src"; + +export interface MinimumWorkerModules { + TaskQueue: TypedClass; + LocalTaskWorkerModule: TypedClass>; +} diff --git a/packages/sequencer/test-integration/workers/modules.ts b/packages/sequencer/test-integration/workers/modules.ts new file mode 100644 index 000000000..7f3481b5d --- /dev/null +++ b/packages/sequencer/test-integration/workers/modules.ts @@ -0,0 +1,50 @@ +import { Runtime } from "@proto-kit/module"; +import { Protocol } from "@proto-kit/protocol"; +import { VanillaProtocolModules } from "@proto-kit/library"; +import { ModulesConfig } from "@proto-kit/common"; +import { BullQueueConfig } from "@proto-kit/deployment"; + +import { ProvenBalance } from "../../test/integration/mocks/ProvenBalance"; +import { ProtocolStateTestHook } from "../../test/integration/mocks/ProtocolStateTestHook"; + +export const runtimeClass = Runtime.from({ + modules: { + Balance: ProvenBalance, + }, + + config: { + Balance: {}, + }, +}); + +export const protocolClass = Protocol.from({ + modules: VanillaProtocolModules.mandatoryModules({ + ProtocolStateTestHook, + }), +}); + +export const runtimeProtocolConfig: ModulesConfig<{ + Runtime: typeof runtimeClass; + Protocol: typeof protocolClass; +}> = { + Runtime: { + Balance: {}, + }, + Protocol: { + AccountState: {}, + BlockProver: {}, + StateTransitionProver: {}, + BlockHeight: {}, + LastStateRoot: {}, + ProtocolStateTestHook: {}, + }, +}; + +export const BullConfig: BullQueueConfig = { + redis: { + host: "localhost", + port: 6379, + password: "password", + db: 1, + }, +}; diff --git a/packages/sequencer/test-integration/workers/worker.test.ts b/packages/sequencer/test-integration/workers/worker.test.ts new file mode 100644 index 000000000..dfc049ac4 --- /dev/null +++ b/packages/sequencer/test-integration/workers/worker.test.ts @@ -0,0 +1,66 @@ +import "reflect-metadata"; +import { AppChain } from "@proto-kit/sdk"; +import { BullQueue } from "@proto-kit/deployment"; +import { container } from "tsyringe"; +import { log, sleep } from "@proto-kit/common"; + +import { + LocalTaskWorkerModule, + Sequencer, + VanillaTaskWorkerModules, +} from "../../src"; + +import { + BullConfig, + protocolClass, + runtimeClass, + runtimeProtocolConfig, +} from "./modules"; +import { MinimumWorkerModules } from "./WorkerModules"; + +describe("worker", () => { + it("spin up and wait", async () => { + const sequencerClass = Sequencer.from({ + modules: { + TaskQueue: BullQueue, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.withoutSettlement() + ), + } satisfies MinimumWorkerModules, + }); + + const app = AppChain.from({ + Runtime: runtimeClass, + Sequencer: sequencerClass, + Protocol: protocolClass, + modules: {}, + }); + + app.configure({ + ...runtimeProtocolConfig, + Sequencer: { + TaskQueue: BullConfig, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + }, + }); + + console.log("Starting worker..."); + + log.setLevel("DEBUG"); + + await app.start(false, container.createChildContainer()); + + console.log("Worker started..."); + + const ready = await new Promise((res) => { + app + .resolve("Sequencer") + .resolve("LocalTaskWorkerModule") + .containerEvents.on("ready", res); + }); + + console.log("Ready received!"); + + await sleep(10000000); + }, 10000000); +}); diff --git a/packages/sequencer/test-integration/workers/workers-proven.test.ts b/packages/sequencer/test-integration/workers/workers-proven.test.ts new file mode 100644 index 000000000..e9368bc16 --- /dev/null +++ b/packages/sequencer/test-integration/workers/workers-proven.test.ts @@ -0,0 +1,133 @@ +import "reflect-metadata"; +import { expectDefined, log, sleep } from "@proto-kit/common"; +import { AppChain } from "@proto-kit/sdk"; +import { container } from "tsyringe"; +import { PrivateKey, UInt64 } from "o1js"; +import { BlockTestService } from "../../test/integration/services/BlockTestService"; +import { BullQueue } from "@proto-kit/deployment"; +import { + BullConfig, + protocolClass, + runtimeClass, + runtimeProtocolConfig, +} from "./modules"; +import { + BatchProducerModule, + BlockProducerModule, + InMemoryDatabase, + ManualBlockTrigger, + NoopBaseLayer, + PrivateMempool, + Sequencer, + SequencerStartupModule, +} from "../../src"; +import { ConstantFeeStrategy } from "../../src/protocol/baselayer/fees/ConstantFeeStrategy"; +import { ChildProcessWorker } from "./ChildProcessWorker"; + +const timeout = 300000; + +describe("worker-proven", () => { + describe("sequencer", () => { + let test: BlockTestService; + + let worker: ChildProcessWorker; + + let appChain: AppChain; + + beforeAll(async () => { + worker = new ChildProcessWorker(); + worker.start(true); + }); + + afterAll(() => { + worker.kill(); + }); + + it( + "should start up and compile", + async () => { + log.setLevel(log.levels.DEBUG); + + const sequencerClass = Sequencer.from({ + modules: { + Database: InMemoryDatabase, + Mempool: PrivateMempool, + BaseLayer: NoopBaseLayer, + BatchProducerModule, + BlockProducerModule, + BlockTrigger: ManualBlockTrigger, + TaskQueue: BullQueue, + FeeStrategy: ConstantFeeStrategy, + SequencerStartupModule, + }, + }); + + const app = AppChain.from({ + Runtime: runtimeClass, + Sequencer: sequencerClass, + Protocol: protocolClass, + modules: {}, + }); + + app.configure({ + Sequencer: { + Database: {}, + BlockTrigger: {}, + Mempool: {}, + BatchProducerModule: {}, + BlockProducerModule: {}, + BaseLayer: {}, + TaskQueue: BullConfig, + FeeStrategy: {}, + SequencerStartupModule: {}, + }, + ...runtimeProtocolConfig, + }); + + try { + // Start AppChain + const childContainer = container.createChildContainer(); + await app.start(false, childContainer); + + test = app.sequencer.dependencyContainer.resolve(BlockTestService); + + appChain = app; + } catch (e) { + console.error(e); + throw e; + } + }, + timeout + ); + + it( + "should produce simple block", + async () => { + expect.assertions(6); + + const privateKey = PrivateKey.random(); + + await test.addTransaction({ + method: ["Balance", "addBalance"], + privateKey, + args: [PrivateKey.random().toPublicKey(), UInt64.from(100)], + }); + + const [block, batch] = await test.produceBlockAndBatch(); + + expectDefined(block); + + expect(block.transactions).toHaveLength(1); + expect(block.transactions[0].status.toBoolean()).toBe(true); + + expectDefined(batch); + + console.log(batch.proof); + + expect(batch.proof.proof.length).toBeGreaterThan(50); + expect(batch.blockHashes).toHaveLength(1); + }, + timeout + ); + }); +}); diff --git a/packages/sequencer/test/TestingSequencer.ts b/packages/sequencer/test/TestingSequencer.ts index d728a588d..9be30dd52 100644 --- a/packages/sequencer/test/TestingSequencer.ts +++ b/packages/sequencer/test/TestingSequencer.ts @@ -13,7 +13,7 @@ import { TaskWorkerModulesRecord, BlockProducerModule, VanillaTaskWorkerModules, - ProtocolStartupModule, + SequencerStartupModule, } from "../src"; import { ConstantFeeStrategy } from "../src/protocol/baselayer/fees/ConstantFeeStrategy"; @@ -27,7 +27,7 @@ export interface DefaultTestingSequencerModules extends SequencerModulesRecord { BlockTrigger: typeof ManualBlockTrigger; TaskQueue: typeof LocalTaskQueue; FeeStrategy: typeof ConstantFeeStrategy; - ProtocolStartupModule: typeof ProtocolStartupModule; + SequencerStartupModule: typeof SequencerStartupModule; } export function testingSequencerFromModules< @@ -60,7 +60,7 @@ export function testingSequencerFromModules< ...modules, // We need to make sure that the taskworkermodule is initialized last LocalTaskWorkerModule: taskWorkerModule, - ProtocolStartupModule: ProtocolStartupModule, + SequencerStartupModule, }, }); } diff --git a/packages/sequencer/test/integration/BlockProduction.test.ts b/packages/sequencer/test/integration/BlockProduction.test.ts index f411bdbf1..d8d9cdc48 100644 --- a/packages/sequencer/test/integration/BlockProduction.test.ts +++ b/packages/sequencer/test/integration/BlockProduction.test.ts @@ -1,4 +1,4 @@ -import { log, range, MOCK_PROOF } from "@proto-kit/common"; +import { log, range, MOCK_PROOF, mapSequential } from "@proto-kit/common"; import { VanillaProtocolModules } from "@proto-kit/library"; import { Runtime, @@ -18,14 +18,7 @@ import { Bool, Field, PrivateKey, PublicKey, Struct, UInt64 } from "o1js"; import "reflect-metadata"; import { container } from "tsyringe"; -import { - AsyncStateService, - BatchStorage, - HistoricalBatchStorage, - ManualBlockTrigger, - PrivateMempool, - Sequencer, -} from "../../src"; +import { BatchStorage, HistoricalBatchStorage, Sequencer } from "../../src"; import { DefaultTestingSequencerModules, testingSequencerFromModules, @@ -33,8 +26,8 @@ import { import { Balance } from "./mocks/Balance"; import { ProtocolStateTestHook } from "./mocks/ProtocolStateTestHook"; -import { createTransaction } from "./utils"; import { NoopRuntime } from "./mocks/NoopRuntime"; +import { BlockTestService } from "./services/BlockTestService"; export class PrimaryTestEvent extends Struct({ message: Bool, @@ -89,13 +82,12 @@ describe("block production", () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars let appChain: AppChain; - let blockTrigger: ManualBlockTrigger; - let mempool: PrivateMempool; + let test: BlockTestService; beforeEach(async () => { // container.reset(); - log.setLevel(log.levels.INFO); + log.setLevel(log.levels.DEBUG); const runtimeClass = Runtime.from({ modules: { @@ -139,7 +131,7 @@ describe("block production", () => { BaseLayer: {}, TaskQueue: {}, FeeStrategy: {}, - ProtocolStartupModule: {}, + SequencerStartupModule: {}, }, Runtime: { Balance: {}, @@ -156,15 +148,27 @@ describe("block production", () => { }, }); - // Start AppChain - await app.start(container.createChildContainer()); + try { + // Start AppChain + await app.start(false, container.createChildContainer()); + } catch (e) { + console.error(e); + throw e; + } + + // Await worker readiness + await new Promise((res) => { + app + .resolve("Sequencer") + .resolve("LocalTaskWorkerModule") + .containerEvents.on("ready", res); + }); appChain = app; ({ runtime, sequencer, protocol } = app); - blockTrigger = sequencer.resolve("BlockTrigger"); - mempool = sequencer.resolve("Mempool"); + test = app.sequencer.dependencyContainer.resolve(BlockTestService); }); it("should produce a dummy block proof", async () => { @@ -175,18 +179,14 @@ describe("block production", () => { const privateKey = PrivateKey.random(); const publicKey = privateKey.toPublicKey(); - await mempool.add( - createTransaction({ - runtime, - method: ["Balance", "setBalanceIf"], - privateKey, - args: [publicKey, UInt64.from(100), Bool(true)], - nonce: 0, - }) - ); + await test.addTransaction({ + method: ["Balance", "setBalanceIf"], + privateKey, + args: [publicKey, UInt64.from(100), Bool(true)], + }); // let [block, batch] = await blockTrigger.produceBlockAndBatch(); - let block = await blockTrigger.produceBlock(); + let block = await test.produceBlock(); expect(block).toBeDefined(); @@ -201,7 +201,7 @@ describe("block production", () => { .resolve("BlockQueue") .getLatestBlock(); - let batch = await blockTrigger.produceBatch(); + let batch = await test.produceBatch(); expect(batch).toBeDefined(); @@ -218,24 +218,14 @@ describe("block production", () => { const retrievedBatch = await batchStorage.getBatchAt(0); expect(retrievedBatch).toBeDefined(); - const stateService = - sequencer.dependencyContainer.resolve( - "AsyncStateService" - ); - - const unprovenStateService = - sequencer.dependencyContainer.resolve( - "UnprovenStateService" - ); - const balanceModule = runtime.resolve("Balance"); const balancesPath = Path.fromKey( balanceModule.balances.path!, balanceModule.balances.keyType, publicKey ); - const newState = await stateService.get(balancesPath); - const newUnprovenState = await unprovenStateService.get(balancesPath); + const newState = await test.getState(balancesPath, "batch"); + const newUnprovenState = await test.getState(balancesPath, "block"); expect(newState).toBeDefined(); expect(newUnprovenState).toBeDefined(); @@ -251,25 +241,21 @@ describe("block production", () => { accountModule.accountState.keyType, publicKey ); - const newAccountState = await stateService.get(accountStatePath); + const newAccountState = await test.getState(accountStatePath, "batch"); expect(newAccountState).toBeDefined(); expect(AccountState.fromFields(newAccountState!).nonce.toBigInt()).toBe(1n); // Second tx - await mempool.add( - createTransaction({ - runtime, - method: ["Balance", "addBalanceToSelf"], - privateKey, - args: [UInt64.from(100), UInt64.from(1)], - nonce: 1, - }) - ); + await test.addTransaction({ + method: ["Balance", "addBalanceToSelf"], + privateKey, + args: [UInt64.from(100), UInt64.from(1)], + }); log.info("Starting second block"); - [block, batch] = await blockTrigger.produceBlockAndBatch(); + [block, batch] = await test.produceBlockAndBatch(); expect(block).toBeDefined(); @@ -282,7 +268,7 @@ describe("block production", () => { expect(batch!.blockHashes).toHaveLength(1); expect(batch!.proof.proof).toBe(MOCK_PROOF); - const state2 = await stateService.get(balancesPath); + const state2 = await test.getState(balancesPath, "batch"); expect(state2).toBeDefined(); expect(UInt64.fromFields(state2!)).toStrictEqual(UInt64.from(200)); @@ -295,42 +281,26 @@ describe("block production", () => { const privateKey = PrivateKey.random(); - await mempool.add( - createTransaction({ - runtime, - method: ["Balance", "setBalanceIf"], - privateKey, - args: [ - PrivateKey.random().toPublicKey(), - UInt64.from(100), - Bool(false), - ], - nonce: 0, - }) - ); + await test.addTransaction({ + method: ["Balance", "setBalanceIf"], + privateKey, + args: [PrivateKey.random().toPublicKey(), UInt64.from(100), Bool(false)], + }); - const [block] = await blockTrigger.produceBlockAndBatch(); + const [block] = await test.produceBlockAndBatch(); expect(block?.transactions).toHaveLength(1); expect(block?.transactions[0].status.toBoolean()).toBe(false); expect(block?.transactions[0].statusMessage).toBe("Condition not met"); - const stateService = - sequencer.dependencyContainer.resolve( - "AsyncStateService" - ); - const unprovenStateService = - sequencer.dependencyContainer.resolve( - "UnprovenStateService" - ); const balanceModule = runtime.resolve("Balance"); const balancesPath = Path.fromKey( balanceModule.balances.path!, balanceModule.balances.keyType, PublicKey.empty() ); - const unprovenState = await unprovenStateService.get(balancesPath); - const newState = await stateService.get(balancesPath); + const unprovenState = await test.getState(balancesPath, "block"); + const newState = await test.getState(balancesPath, "batch"); // Assert that state is not set expect(unprovenState).toBeUndefined(); @@ -347,20 +317,15 @@ describe("block production", () => { const increment = 100; - const p = range(0, numberTxs).map(async (index) => { - await mempool.add( - createTransaction({ - runtime, - method: ["Balance", "addBalanceToSelf"], - privateKey, - args: [UInt64.from(increment), UInt64.from(0)], - nonce: index, - }) - ); + await mapSequential(range(0, numberTxs), async (index) => { + await test.addTransaction({ + method: ["Balance", "addBalanceToSelf"], + privateKey, + args: [UInt64.from(increment), UInt64.from(0)], + }); }); - await Promise.all(p); - const block = await blockTrigger.produceBlock(); + const block = await test.produceBlock(); expect(block).toBeDefined(); expect(block!.transactions).toHaveLength(numberTxs); @@ -380,22 +345,18 @@ describe("block production", () => { ); }); - const batch = await blockTrigger.produceBatch(); + const batch = await test.produceBatch(); expect(batch!.blockHashes).toHaveLength(1); expect(batch!.proof.proof).toBe(MOCK_PROOF); - const stateService = - sequencer.dependencyContainer.resolve( - "AsyncStateService" - ); const balanceModule = runtime.resolve("Balance"); const balancesPath = Path.fromKey( balanceModule.balances.path!, balanceModule.balances.keyType, publicKey ); - const newState = await stateService.get(balancesPath); + const newState = await test.getState(balancesPath, "batch"); expect(newState).toBeDefined(); expect(UInt64.fromFields(newState!)).toStrictEqual( @@ -409,45 +370,33 @@ describe("block production", () => { const pk1 = PrivateKey.random(); const pk2 = PrivateKey.random(); - await mempool.add( - createTransaction({ - runtime, - method: ["Balance", "setBalanceIf"], - privateKey: pk1, - args: [pk1.toPublicKey(), UInt64.from(100), Bool(false)], - nonce: 0, - }) - ); - await mempool.add( - createTransaction({ - runtime, - method: ["Balance", "setBalanceIf"], - privateKey: pk2, - args: [pk2.toPublicKey(), UInt64.from(100), Bool(true)], - nonce: 0, - }) - ); + await test.addTransaction({ + method: ["Balance", "setBalanceIf"], + privateKey: pk1, + args: [pk1.toPublicKey(), UInt64.from(100), Bool(false)], + }); + await test.addTransaction({ + method: ["Balance", "setBalanceIf"], + privateKey: pk2, + args: [pk2.toPublicKey(), UInt64.from(100), Bool(true)], + }); - const block = await blockTrigger.produceBlock(); - await blockTrigger.produceBlock(); - const batch = await blockTrigger.produceBatch(); + const block = await test.produceBlock(); + await test.produceBlock(); + const batch = await test.produceBatch(); expect(block).toBeDefined(); expect(batch!.blockHashes).toHaveLength(2); expect(block!.transactions).toHaveLength(2); - const stateService = - sequencer.dependencyContainer.resolve( - "AsyncStateService" - ); const balanceModule = runtime.resolve("Balance"); const balancesPath1 = Path.fromKey( balanceModule.balances.path!, balanceModule.balances.keyType, pk1.toPublicKey() ); - const newState1 = await stateService.get(balancesPath1); + const newState1 = await test.getState(balancesPath1, "batch"); expect(newState1).toBeUndefined(); @@ -456,18 +405,20 @@ describe("block production", () => { balanceModule.balances.keyType, pk2.toPublicKey() ); - const newState2 = await stateService.get(balancesPath2); + const newState2 = await test.getState(balancesPath2, "batch"); expect(newState2).toBeDefined(); expect(UInt64.fromFields(newState2!)).toStrictEqual(UInt64.from(100)); - await blockTrigger.produceBlock(); - await blockTrigger.produceBlock(); - const proven2 = await blockTrigger.produceBatch(); + await test.produceBlock(); + await test.produceBlock(); + const proven2 = await test.produceBatch(); expect(proven2?.blockHashes.length).toBe(2); }, 720_000); + // TODO Test with batch that only consists of empty blocks + it.skip.each([ [2, 1, 1], [1, 2, 1], @@ -498,24 +449,20 @@ describe("block production", () => { for (let i = 0; i < batches; i++) { for (let j = 0; j < blocksPerBatch; j++) { for (let k = 0; k < txsPerBlock; k++) { - await mempool.add( - createTransaction({ - runtime, - method: ["Balance", "addBalance"], - privateKey: sender, - args: [ - keys[iterationIndex].toPublicKey(), - UInt64.from(increment * (iterationIndex + 1)), - ], - nonce: iterationIndex, - }) - ); + await test.addTransaction({ + method: ["Balance", "addBalance"], + privateKey: sender, + args: [ + keys[iterationIndex].toPublicKey(), + UInt64.from(increment * (iterationIndex + 1)), + ], + }); iterationIndex += 1; } // Produce block - const block = await blockTrigger.produceBlock(); + const block = await test.produceBlock(); expect(block).toBeDefined(); @@ -525,7 +472,7 @@ describe("block production", () => { } } - const batch = await blockTrigger.produceBatch(); + const batch = await test.produceBatch(); expect(batch).toBeDefined(); expect(batch!.blockHashes).toHaveLength(blocksPerBatch); @@ -541,17 +488,13 @@ describe("block production", () => { const field = Field(100); - await mempool.add( - createTransaction({ - runtime, - method: ["Balance", "lotOfSTs"], - privateKey, - args: [field], - nonce: 0, - }) - ); + await test.addTransaction({ + method: ["Balance", "lotOfSTs"], + privateKey, + args: [field], + }); - const [block, batch] = await blockTrigger.produceBlockAndBatch(); + const [block, batch] = await test.produceBlockAndBatch(); expect(block).toBeDefined(); expect(batch).toBeDefined(); @@ -564,12 +507,8 @@ describe("block production", () => { expect(batch!.blockHashes).toHaveLength(1); expect(batch!.proof.proof).toBe(MOCK_PROOF); - const stateService = - sequencer.dependencyContainer.resolve( - "AsyncStateService" - ); const supplyPath = Path.fromProperty("Balance", "totalSupply"); - const newState = await stateService.get(supplyPath); + const newState = await test.getState(supplyPath, "batch"); expect(newState).toBeDefined(); expect(UInt64.fromFields(newState!)).toStrictEqual( @@ -585,7 +524,7 @@ describe("block production", () => { pk2 ); - const newBalance = await stateService.get(balancesPath); + const newBalance = await test.getState(balancesPath, "batch"); expect(newBalance).toBeDefined(); expect(UInt64.fromFields(newBalance!)).toStrictEqual(UInt64.from(200)); @@ -596,18 +535,13 @@ describe("block production", () => { const privateKey = PrivateKey.random(); - const tx = createTransaction({ - runtime, + await test.addTransaction({ method: ["NoopRuntime", "emittingNoSTs"], privateKey, args: [], - nonce: 0, }); - console.log(tx.argsHash().toString()); - console.log(tx.toProtocolTransaction().transaction.argsHash.toString()); - await mempool.add(tx); - const block = await blockTrigger.produceBlock(); + const block = await test.produceBlock(); expect(block).toBeDefined(); @@ -618,7 +552,7 @@ describe("block production", () => { expect(block!.transactions[0].stateTransitions).toHaveLength(0); expect(block!.transactions[0].protocolTransitions).toHaveLength(2); - const batch = await blockTrigger.produceBatch(); + const batch = await test.produceBatch(); expect(batch).toBeDefined(); @@ -631,14 +565,11 @@ describe("block production", () => { const privateKey = PrivateKey.random(); - const tx = createTransaction({ - runtime, + await test.addTransaction({ method: ["EventMaker", "makeEvent"], privateKey, args: [], - nonce: 0, }); - await mempool.add(tx); const firstExpectedEvent = { eventType: PrimaryTestEvent, @@ -665,7 +596,7 @@ describe("block production", () => { data: secondExpectedEvent.eventType.toFields(secondExpectedEvent.event), }; - const block = await blockTrigger.produceBlock(); + const block = await test.produceBlock(); expect(block).toBeDefined(); @@ -674,7 +605,7 @@ describe("block production", () => { expect(block!.transactions[0].events[0]).toStrictEqual(firstEventReduced); expect(block!.transactions[0].events[1]).toStrictEqual(secondEventReduced); - const batch = await blockTrigger.produceBatch(); + const batch = await test.produceBatch(); expect(batch).toBeDefined(); diff --git a/packages/sequencer/test/integration/Proven.test.ts b/packages/sequencer/test/integration/Proven.test.ts new file mode 100644 index 000000000..08026a7ee --- /dev/null +++ b/packages/sequencer/test/integration/Proven.test.ts @@ -0,0 +1,134 @@ +import "reflect-metadata"; +import { expectDefined, log } from "@proto-kit/common"; +import { Runtime } from "@proto-kit/module"; +import { Protocol } from "@proto-kit/protocol"; +import { VanillaProtocolModules } from "@proto-kit/library"; +import { AppChain } from "@proto-kit/sdk"; +import { container } from "tsyringe"; +import { PrivateKey, UInt64 } from "o1js"; + +import { testingSequencerFromModules } from "../TestingSequencer"; + +import { ProtocolStateTestHook } from "./mocks/ProtocolStateTestHook"; +import { BlockTestService } from "./services/BlockTestService"; +import { ProvenBalance } from "./mocks/ProvenBalance"; + +const timeout = 300000; + +describe("Proven", () => { + let test: BlockTestService; + + it( + "should start up and compile", + async () => { + log.setLevel(log.levels.DEBUG); + const runtimeClass = Runtime.from({ + modules: { + Balance: ProvenBalance, + }, + + config: { + Balance: {}, + }, + }); + + const sequencerClass = testingSequencerFromModules({}); + + // TODO Analyze how we can get rid of the library import for mandatory modules + const protocolClass = Protocol.from({ + modules: VanillaProtocolModules.mandatoryModules({ + ProtocolStateTestHook, + // ProtocolStateTestHook2, + }), + // modules: VanillaProtocolModules.with({}), + }); + + const app = AppChain.from({ + Runtime: runtimeClass, + Sequencer: sequencerClass, + Protocol: protocolClass, + modules: {}, + }); + + app.configure({ + Sequencer: { + Database: {}, + BlockTrigger: {}, + Mempool: {}, + BatchProducerModule: {}, + BlockProducerModule: {}, + LocalTaskWorkerModule: {}, + BaseLayer: {}, + TaskQueue: {}, + FeeStrategy: {}, + SequencerStartupModule: {}, + }, + Runtime: { + Balance: {}, + }, + Protocol: { + AccountState: {}, + BlockProver: {}, + StateTransitionProver: {}, + BlockHeight: {}, + LastStateRoot: {}, + ProtocolStateTestHook: {}, + // ProtocolStateTestHook2: {}, + }, + }); + + try { + // Start AppChain + const childContainer = container.createChildContainer(); + await app.start(true, childContainer); + + const ready = await new Promise((res) => { + app + .resolve("Sequencer") + .resolve("LocalTaskWorkerModule") + .containerEvents.on("ready", res); + }); + + expect(ready).toBe(true); + + test = app.sequencer.dependencyContainer.resolve(BlockTestService); + } catch (e) { + console.error(e); + throw e; + } + }, + timeout + ); + + it( + "should produce simple block", + async () => { + expect.assertions(6); + + log.setLevel("INFO"); + + const privateKey = PrivateKey.random(); + + await test.addTransaction({ + method: ["Balance", "addBalance"], + privateKey, + args: [PrivateKey.random().toPublicKey(), UInt64.from(100)], + }); + + const [block, batch] = await test.produceBlockAndBatch(); + + expectDefined(block); + + expect(block.transactions).toHaveLength(1); + expect(block.transactions[0].status.toBoolean()).toBe(true); + + expectDefined(batch); + + console.log(batch.proof); + + expect(batch.proof.proof.length).toBeGreaterThan(50); + expect(batch.blockHashes).toHaveLength(1); + }, + timeout + ); +}); diff --git a/packages/sequencer/test/integration/StorageIntegration.test.ts b/packages/sequencer/test/integration/StorageIntegration.test.ts index 687beb163..546f47258 100644 --- a/packages/sequencer/test/integration/StorageIntegration.test.ts +++ b/packages/sequencer/test/integration/StorageIntegration.test.ts @@ -108,7 +108,7 @@ describe.each([["InMemory", InMemoryDatabase]])( BaseLayer: {}, TaskQueue: {}, FeeStrategy: {}, - ProtocolStartupModule: {}, + SequencerStartupModule: {}, }, Protocol: { AccountState: {}, diff --git a/packages/sequencer/test/integration/mocks/ProvenBalance.ts b/packages/sequencer/test/integration/mocks/ProvenBalance.ts new file mode 100644 index 000000000..ff6cbbeca --- /dev/null +++ b/packages/sequencer/test/integration/mocks/ProvenBalance.ts @@ -0,0 +1,39 @@ +import { + runtimeMethod, + runtimeModule, + RuntimeModule, + state, +} from "@proto-kit/module"; +import { log, Presets } from "@proto-kit/common"; +import { PublicKey, UInt64 } from "o1js"; +import { Admin } from "@proto-kit/module/test/modules/Admin"; +import { State, StateMap } from "@proto-kit/protocol"; + +@runtimeModule() +export class ProvenBalance extends RuntimeModule { + public static presets = {} satisfies Presets; + + @state() public totalSupply = State.from(UInt64); + + @state() public balances = StateMap.from( + PublicKey, + UInt64 + ); + + public constructor(public admin: Admin) { + super(); + } + + @runtimeMethod() + public async addBalance(address: PublicKey, value: UInt64) { + const totalSupply = await this.totalSupply.get(); + await this.totalSupply.set(totalSupply.orElse(UInt64.zero).add(value)); + + const balance = await this.balances.get(address); + + log.provable.debug("Balance:", balance.isSome, balance.value); + + const newBalance = balance.orElse(UInt64.zero).add(value); + await this.balances.set(address, newBalance); + } +} diff --git a/packages/sequencer/test/integration/services/BlockTestService.ts b/packages/sequencer/test/integration/services/BlockTestService.ts new file mode 100644 index 000000000..f51c64393 --- /dev/null +++ b/packages/sequencer/test/integration/services/BlockTestService.ts @@ -0,0 +1,67 @@ +import { inject, injectable, Lifecycle, scoped } from "tsyringe"; +import { Field, PrivateKey } from "o1js"; +import { Runtime, RuntimeModulesRecord } from "@proto-kit/module"; +import { ArgumentTypes } from "@proto-kit/common"; + +import { + AsyncStateService, + ManualBlockTrigger, + PrivateMempool, +} from "../../../src"; +import { createTransaction } from "../utils"; + +@injectable() +@scoped(Lifecycle.ContainerScoped) +export class BlockTestService { + public constructor( + @inject("BlockTrigger") private trigger: ManualBlockTrigger, + @inject("Mempool") private mempool: PrivateMempool, + @inject("Runtime") private runtime: Runtime, + @inject("AsyncStateService") private batchStateService: AsyncStateService, + @inject("UnprovenStateService") private blockStateService: AsyncStateService + ) {} + + private nonces: Record = {}; + + public async addTransaction({ + privateKey, + method, + args, + }: { + privateKey: PrivateKey; + method: [string, string]; + args: ArgumentTypes; + }) { + const nonce = this.nonces[privateKey.toPublicKey().toBase58()] ?? 0; + + await this.mempool.add( + createTransaction({ + runtime: this.runtime, + privateKey, + method, + args, + nonce, + }) + ); + + this.nonces[privateKey.toPublicKey().toBase58()] = nonce + 1; + } + + public async getState(path: Field, type: "block" | "batch" = "block") { + const service = + type === "batch" ? this.batchStateService : this.blockStateService; + return await service.get(path); + } + + public async produceBlock() { + return await this.trigger.produceBlock(); + } + + public async produceBatch() { + return await this.trigger.produceBatch(); + } + + public async produceBlockAndBatch() { + return await this.trigger.produceBlockAndBatch(); + } +} diff --git a/packages/sequencer/test/settlement/Settlement.ts b/packages/sequencer/test/settlement/Settlement.ts index f28c98581..c55d19449 100644 --- a/packages/sequencer/test/settlement/Settlement.ts +++ b/packages/sequencer/test/settlement/Settlement.ts @@ -178,7 +178,7 @@ export const settlementTestFn = ( SettlementModule: { feepayer: sequencerKey, }, - ProtocolStartupModule: {}, + SequencerStartupModule: {}, TaskQueue: { simulatedDuration: 0, @@ -259,7 +259,7 @@ export const settlementTestFn = ( beforeAll(async () => { appChain = setupAppChain(); - await appChain.start(container.createChildContainer()); + await appChain.start(false, container.createChildContainer()); settlementModule = appChain.sequencer.resolve( "SettlementModule" diff --git a/packages/stack/src/scripts/graphql/server.ts b/packages/stack/src/scripts/graphql/server.ts index 6f6cc3d86..c13969042 100644 --- a/packages/stack/src/scripts/graphql/server.ts +++ b/packages/stack/src/scripts/graphql/server.ts @@ -236,7 +236,7 @@ export async function startServer() { }, }); - await appChain.start(container.createChildContainer()); + await appChain.start(false, container.createChildContainer()); // const pk = PublicKey.fromBase58( // "B62qmETai5Y8vvrmWSU8F4NX7pTyPqYLMhc1pgX3wD8dGc2wbCWUcqP" // ); diff --git a/packages/stack/src/scripts/worker/sequencer.ts b/packages/stack/src/scripts/worker/sequencer.ts index 99e9ef4b4..5718af8ca 100644 --- a/packages/stack/src/scripts/worker/sequencer.ts +++ b/packages/stack/src/scripts/worker/sequencer.ts @@ -65,7 +65,7 @@ sequencer.configure({ password: "password", }, }, - ProtocolStartupModule: {}, + SequencerStartupModule: {}, GraphqlServer: { host: "0.0.0.0", port: 8080,