diff --git a/.circleci/config.yml b/.circleci/config.yml index 68a5071a9c5c..89aa93671526 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,7 +48,9 @@ checkout: &checkout git fetch --depth 50 --filter=blob:none origin $CIRCLE_SHA1 git checkout FETCH_HEAD # Initialize submodules recursively - git submodule update --init --recursive build-system yarn-project/foundation + git submodule update --init --recursive circuits build-system yarn-project/foundation + # We have build problems with symlinks in yarn-project. Resolve them. + rm yarn-project/circuits.js && cp -r circuits/ts yarn-project/circuits.js # Called setup_env to setup a bunch of global variables used throughout the rest of the build process. # It takes the required CCI environment variables as inputs, and gives them normalised names for the rest of diff --git a/.vscode/settings.json b/.vscode/settings.json index 9b50a90191d1..4a99f6a9425b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -124,5 +124,6 @@ }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - } + }, + "cmake.sourceDirectory": "${workspaceFolder}/barretenberg/cpp" } diff --git a/bootstrap.sh b/bootstrap.sh index d4b2c0c171ea..20b2f885758f 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -41,13 +41,13 @@ yarn install --immutable cd .. # make sure to run yarn install from foundation, has its own yarn.lock -pushd yarn-project/foundation >/dev/null -yarn install -popd >/dev/null +cd yarn-project/foundation +yarn install --immutable +cd ../.. # We only bootstrap projects that produce artefacts needed for running end-to-end tests. PROJECTS=( - # "yarn-project/foundation:yarn build" + "yarn-project/foundation:yarn build" "yarn-project/ethereum.js:yarn build" "yarn-project/merkle-tree:yarn build" "yarn-project/archiver:yarn build" diff --git a/build_manifest.json b/build_manifest.json index c6817fce918c..4a7e18cda657 100644 --- a/build_manifest.json +++ b/build_manifest.json @@ -50,7 +50,7 @@ "projectDir": "yarn-project/archiver", "dockerfile": "archiver/Dockerfile", "rebuildPatterns": ["^yarn-project/archiver/"], - "dependencies": ["yarn-project-base", "ethereum.js"] + "dependencies": ["yarn-project-base", "ethereum.js", "l1-contracts"] }, "aztec-cli": { "buildDir": "yarn-project", @@ -59,13 +59,6 @@ "rebuildPatterns": ["^yarn-project/aztec-cli/"], "dependencies": ["aztec.js"] }, - "aztec-node": { - "buildDir": "yarn-project", - "projectDir": "yarn-project/aztec-node", - "dockerfile": "aztec-node/Dockerfile", - "rebuildPatterns": ["^yarn-project/aztec-node/"], - "dependencies": ["foundation", "p2p", "world-state", "ethereum.js"] - }, "aztec-rpc": { "buildDir": "yarn-project", "projectDir": "yarn-project/aztec-rpc", @@ -134,7 +127,7 @@ "projectDir": "yarn-project/p2p", "dockerfile": "p2p/Dockerfile", "rebuildPatterns": ["^yarn-project/p2p/"], - "dependencies": ["yarn-project-base", "archiver"] + "dependencies": ["yarn-project-base", "archiver", "foundation"] }, "prover-client": { "buildDir": "yarn-project", @@ -143,18 +136,44 @@ "rebuildPatterns": ["^yarn-project/prover-client/"], "dependencies": ["yarn-project-base"] }, + "aztec-node": { + "buildDir": "yarn-project", + "projectDir": "yarn-project/aztec-node", + "dockerfile": "aztec-node/Dockerfile", + "rebuildPatterns": ["^yarn-project/aztec-node/"], + "dependencies": [ + "yarn-project-base", + "archiver", + "world-state", + "p2p", + "sequencer-client", + "ethereum.js", + "circuits.js" + ] + }, "sequencer-client": { "buildDir": "yarn-project", "projectDir": "yarn-project/sequencer-client", "dockerfile": "sequencer-client/Dockerfile", "rebuildPatterns": ["^yarn-project/sequencer-client/"], - "dependencies": ["yarn-project-base"] + "dependencies": [ + "yarn-project-base", + "world-state", + "foundation", + "p2p", + "archiver" + ] }, "world-state": { "buildDir": "yarn-project", "projectDir": "yarn-project/world-state", "dockerfile": "world-state/Dockerfile", "rebuildPatterns": ["^yarn-project/world-state/"], - "dependencies": ["yarn-project-base", "merkle-tree"] + "dependencies": [ + "yarn-project-base", + "merkle-tree", + "archiver", + "foundation" + ] } } diff --git a/circuits b/circuits index 6b20080ceff9..f127997ab8da 160000 --- a/circuits +++ b/circuits @@ -1 +1 @@ -Subproject commit 6b20080ceff994387c8e2cd4f58142ff7b740864 +Subproject commit f127997ab8da1d239ef93df99df184e45ecb0782 diff --git a/l1-contracts b/l1-contracts index 7f01e8875c18..daacc374bb9b 160000 --- a/l1-contracts +++ b/l1-contracts @@ -1 +1 @@ -Subproject commit 7f01e8875c187e56feda3e3a7bf6d8d1ce638b62 +Subproject commit daacc374bb9b1c59bfc90b50e6bc97114ed4fbd6 diff --git a/yarn-project/.yalc/@aztec/wasm/.eslintrc.cjs b/yarn-project/.yalc/@aztec/wasm/.eslintrc.cjs new file mode 100644 index 000000000000..9cf806b1500f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/.eslintrc.cjs @@ -0,0 +1,6 @@ +require('@rushstack/eslint-patch/modern-module-resolution'); + +module.exports = { + extends: ['@aztec/eslint-config'], + parserOptions: { tsconfigRootDir: __dirname }, +}; diff --git a/yarn-project/.yalc/@aztec/wasm/.tsbuildinfo b/yarn-project/.yalc/@aztec/wasm/.tsbuildinfo new file mode 100644 index 000000000000..eb474691c49f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/.tsbuildinfo @@ -0,0 +1 @@ +{"program":{"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.es2021.d.ts","../node_modules/typescript/lib/lib.es2022.d.ts","../node_modules/typescript/lib/lib.esnext.d.ts","../node_modules/typescript/lib/lib.dom.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2019.intl.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.es2021.promise.d.ts","../node_modules/typescript/lib/lib.es2021.string.d.ts","../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../node_modules/typescript/lib/lib.es2021.intl.d.ts","../node_modules/typescript/lib/lib.es2022.array.d.ts","../node_modules/typescript/lib/lib.es2022.error.d.ts","../node_modules/typescript/lib/lib.es2022.intl.d.ts","../node_modules/typescript/lib/lib.es2022.object.d.ts","../node_modules/typescript/lib/lib.es2022.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2022.string.d.ts","../node_modules/typescript/lib/lib.esnext.intl.d.ts","../node_modules/tslib/tslib.d.ts","../log/dest/index.d.ts","../node_modules/buffer/index.d.ts","./src/memory_fifo.ts","./src/wasm/empty_wasi_sdk.ts","./src/wasm/wasm_module.ts","./src/transport/dispatch/create_dispatch_fn.ts","./src/transport/dispatch/messages.ts","./src/transport/interface/socket.ts","./src/transport/interface/connector.ts","./src/transport/transport_client.ts","./src/transport/interface/transferable.ts","./src/transport/dispatch/create_dispatch_proxy.ts","./src/transport/interface/listener.ts","./src/transport/transport_server.ts","./src/transport/browser/message_port_socket.ts","./src/transport/browser/worker_connector.ts","./src/transport/browser/worker_listener.ts","./src/transport/browser/shared_worker_connector.ts","./src/transport/browser/shared_worker_listener.ts","./src/transport/browser/index.ts","./src/transport/node/node_connector_socket.ts","./src/transport/node/node_connector.ts","./src/transport/node/node_listener_socket.ts","./src/transport/node/node_listener.ts","./src/transport/node/index.ts","./src/transport/index.ts","./src/worker/wasm_worker.ts","./src/worker/browser/web_worker.ts","./src/worker/data_store.ts","../node_modules/@types/node/assert.d.ts","../node_modules/@types/node/assert/strict.d.ts","../node_modules/@types/node/globals.d.ts","../node_modules/@types/node/async_hooks.d.ts","../node_modules/@types/node/buffer.d.ts","../node_modules/@types/node/child_process.d.ts","../node_modules/@types/node/cluster.d.ts","../node_modules/@types/node/console.d.ts","../node_modules/@types/node/constants.d.ts","../node_modules/@types/node/crypto.d.ts","../node_modules/@types/node/dgram.d.ts","../node_modules/@types/node/diagnostics_channel.d.ts","../node_modules/@types/node/dns.d.ts","../node_modules/@types/node/dns/promises.d.ts","../node_modules/@types/node/domain.d.ts","../node_modules/@types/node/dom-events.d.ts","../node_modules/@types/node/events.d.ts","../node_modules/@types/node/fs.d.ts","../node_modules/@types/node/fs/promises.d.ts","../node_modules/@types/node/http.d.ts","../node_modules/@types/node/http2.d.ts","../node_modules/@types/node/https.d.ts","../node_modules/@types/node/inspector.d.ts","../node_modules/@types/node/module.d.ts","../node_modules/@types/node/net.d.ts","../node_modules/@types/node/os.d.ts","../node_modules/@types/node/path.d.ts","../node_modules/@types/node/perf_hooks.d.ts","../node_modules/@types/node/process.d.ts","../node_modules/@types/node/punycode.d.ts","../node_modules/@types/node/querystring.d.ts","../node_modules/@types/node/readline.d.ts","../node_modules/@types/node/readline/promises.d.ts","../node_modules/@types/node/repl.d.ts","../node_modules/@types/node/stream.d.ts","../node_modules/@types/node/stream/promises.d.ts","../node_modules/@types/node/stream/consumers.d.ts","../node_modules/@types/node/stream/web.d.ts","../node_modules/@types/node/string_decoder.d.ts","../node_modules/@types/node/test.d.ts","../node_modules/@types/node/timers.d.ts","../node_modules/@types/node/timers/promises.d.ts","../node_modules/@types/node/tls.d.ts","../node_modules/@types/node/trace_events.d.ts","../node_modules/@types/node/tty.d.ts","../node_modules/@types/node/url.d.ts","../node_modules/@types/node/util.d.ts","../node_modules/@types/node/v8.d.ts","../node_modules/@types/node/vm.d.ts","../node_modules/@types/node/wasi.d.ts","../node_modules/@types/node/worker_threads.d.ts","../node_modules/@types/node/zlib.d.ts","../node_modules/@types/node/globals.global.d.ts","../node_modules/@types/node/index.d.ts","../node_modules/@types/abstract-leveldown/index.d.ts","../node_modules/@types/level-errors/index.d.ts","../node_modules/@types/levelup/index.d.ts","../node_modules/@types/memdown/index.d.ts","./src/worker/browser/web_data_store.ts","./src/worker/browser/index.ts","./src/worker/node/node_worker.ts","../node_modules/@types/leveldown/index.d.ts","./src/worker/node/node_data_store.ts","./src/worker/node/index.ts","./src/worker/worker_pool.ts","./src/worker/index.ts","./src/wasm/async_call_state.ts","./src/wasm/index.ts","./src/index.ts","./src/worker/browser/start_web_module.ts","./src/worker/node/start_node_module.ts","../node_modules/@babel/types/lib/index.d.ts","../node_modules/@types/babel__generator/index.d.ts","../node_modules/@babel/parser/typings/babel-parser.d.ts","../node_modules/@types/babel__template/index.d.ts","../node_modules/@types/babel__traverse/index.d.ts","../node_modules/@types/babel__core/index.d.ts","../node_modules/@types/bn.js/index.d.ts","../node_modules/@types/detect-node/index.d.ts","../node_modules/@types/elliptic/index.d.ts","../node_modules/@types/graceful-fs/index.d.ts","../node_modules/@types/hdkey/index.d.ts","../node_modules/@types/istanbul-lib-coverage/index.d.ts","../node_modules/@types/istanbul-lib-report/index.d.ts","../node_modules/@types/istanbul-reports/index.d.ts","../node_modules/@jest/expect-utils/build/index.d.ts","../node_modules/chalk/index.d.ts","../node_modules/@sinclair/typebox/typebox.d.ts","../node_modules/@jest/schemas/build/index.d.ts","../node_modules/jest-diff/node_modules/pretty-format/build/index.d.ts","../node_modules/jest-diff/build/index.d.ts","../node_modules/expect/node_modules/jest-matcher-utils/build/index.d.ts","../node_modules/expect/build/index.d.ts","../node_modules/@types/jest/node_modules/pretty-format/build/index.d.ts","../node_modules/@types/jest/index.d.ts","../node_modules/@types/json-schema/index.d.ts","../node_modules/@types/prettier/index.d.ts","../node_modules/@types/semver/classes/semver.d.ts","../node_modules/@types/semver/functions/parse.d.ts","../node_modules/@types/semver/functions/valid.d.ts","../node_modules/@types/semver/functions/clean.d.ts","../node_modules/@types/semver/functions/inc.d.ts","../node_modules/@types/semver/functions/diff.d.ts","../node_modules/@types/semver/functions/major.d.ts","../node_modules/@types/semver/functions/minor.d.ts","../node_modules/@types/semver/functions/patch.d.ts","../node_modules/@types/semver/functions/prerelease.d.ts","../node_modules/@types/semver/functions/compare.d.ts","../node_modules/@types/semver/functions/rcompare.d.ts","../node_modules/@types/semver/functions/compare-loose.d.ts","../node_modules/@types/semver/functions/compare-build.d.ts","../node_modules/@types/semver/functions/sort.d.ts","../node_modules/@types/semver/functions/rsort.d.ts","../node_modules/@types/semver/functions/gt.d.ts","../node_modules/@types/semver/functions/lt.d.ts","../node_modules/@types/semver/functions/eq.d.ts","../node_modules/@types/semver/functions/neq.d.ts","../node_modules/@types/semver/functions/gte.d.ts","../node_modules/@types/semver/functions/lte.d.ts","../node_modules/@types/semver/functions/cmp.d.ts","../node_modules/@types/semver/functions/coerce.d.ts","../node_modules/@types/semver/classes/comparator.d.ts","../node_modules/@types/semver/classes/range.d.ts","../node_modules/@types/semver/functions/satisfies.d.ts","../node_modules/@types/semver/ranges/max-satisfying.d.ts","../node_modules/@types/semver/ranges/min-satisfying.d.ts","../node_modules/@types/semver/ranges/to-comparators.d.ts","../node_modules/@types/semver/ranges/min-version.d.ts","../node_modules/@types/semver/ranges/valid.d.ts","../node_modules/@types/semver/ranges/outside.d.ts","../node_modules/@types/semver/ranges/gtr.d.ts","../node_modules/@types/semver/ranges/ltr.d.ts","../node_modules/@types/semver/ranges/intersects.d.ts","../node_modules/@types/semver/ranges/simplify.d.ts","../node_modules/@types/semver/ranges/subset.d.ts","../node_modules/@types/semver/internals/identifiers.d.ts","../node_modules/@types/semver/index.d.ts","../node_modules/@types/stack-utils/index.d.ts","../node_modules/@types/uuid/index.d.ts","../node_modules/@types/yargs-parser/index.d.ts","../node_modules/@types/yargs/index.d.ts"],"fileInfos":[{"version":"8730f4bf322026ff5229336391a18bcaa1f94d4f82416c8b2f3954e2ccaae2ba","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","impliedFormat":1},{"version":"7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","impliedFormat":1},{"version":"8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","impliedFormat":1},{"version":"5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","impliedFormat":1},{"version":"4b421cbfb3a38a27c279dec1e9112c3d1da296f77a1a85ddadf7e7a425d45d18","impliedFormat":1},{"version":"1fc5ab7a764205c68fa10d381b08417795fc73111d6dd16b5b1ed36badb743d9","impliedFormat":1},{"version":"746d62152361558ea6d6115cf0da4dd10ede041d14882ede3568bce5dc4b4f1f","impliedFormat":1},{"version":"d11a03592451da2d1065e09e61f4e2a9bf68f780f4f6623c18b57816a9679d17","impliedFormat":1},{"version":"aea179452def8a6152f98f63b191b84e7cbd69b0e248c91e61fb2e52328abe8c","impliedFormat":1},{"version":"3aafcb693fe5b5c3bd277bd4c3a617b53db474fe498fc5df067c5603b1eebde7","affectsGlobalScope":true,"impliedFormat":1},{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cc8c5a3bac513368b0157f3d8b31cfdcfe78b56d3724f30f80ed9715e404af8","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true,"impliedFormat":1},{"version":"5f406584aef28a331c36523df688ca3650288d14f39c5d2e555c95f0d2ff8f6f","affectsGlobalScope":true,"impliedFormat":1},{"version":"22f230e544b35349cfb3bd9110b6ef37b41c6d6c43c3314a31bd0d9652fcec72","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ea0b55f6b315cf9ac2ad622b0a7813315bb6e97bf4bb3fbf8f8affbca7dc695","affectsGlobalScope":true,"impliedFormat":1},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb26de841c52236d8222f87e9e6a235332e0788af8c87a71e9e210314300410a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true,"impliedFormat":1},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true,"impliedFormat":1},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true,"impliedFormat":1},{"version":"81cac4cbc92c0c839c70f8ffb94eb61e2d32dc1c3cf6d95844ca099463cf37ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true,"impliedFormat":1},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true,"impliedFormat":1},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true,"impliedFormat":1},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true,"impliedFormat":1},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true,"impliedFormat":1},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true,"impliedFormat":1},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true,"impliedFormat":1},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true,"impliedFormat":1},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true,"impliedFormat":1},{"version":"5e5e095c4470c8bab227dbbc61374878ecead104c74ab9960d3adcccfee23205","affectsGlobalScope":true,"impliedFormat":1},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7f680a43f8cd12a6b6122c07c54ba40952b0c8aa140dcfcf32eb9e6cb028596","affectsGlobalScope":true,"impliedFormat":1},{"version":"3787b83e297de7c315d55d4a7c546ae28e5f6c0a361b7a1dcec1f1f50a54ef11","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7e8e1d368290e9295ef18ca23f405cf40d5456fa9f20db6373a61ca45f75f40","affectsGlobalScope":true,"impliedFormat":1},{"version":"faf0221ae0465363c842ce6aa8a0cbda5d9296940a8e26c86e04cc4081eea21e","affectsGlobalScope":true,"impliedFormat":1},{"version":"06393d13ea207a1bfe08ec8d7be562549c5e2da8983f2ee074e00002629d1871","affectsGlobalScope":true,"impliedFormat":1},{"version":"2768ef564cfc0689a1b76106c421a2909bdff0acbe87da010785adab80efdd5c","affectsGlobalScope":true,"impliedFormat":1},{"version":"b248e32ca52e8f5571390a4142558ae4f203ae2f94d5bac38a3084d529ef4e58","affectsGlobalScope":true,"impliedFormat":1},{"version":"6c55633c733c8378db65ac3da7a767c3cf2cf3057f0565a9124a16a3a2019e87","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb4416144c1bf0323ccbc9afb0ab289c07312214e8820ad17d709498c865a3fe","affectsGlobalScope":true,"impliedFormat":1},{"version":"5b0ca94ec819d68d33da516306c15297acec88efeb0ae9e2b39f71dbd9685ef7","affectsGlobalScope":true,"impliedFormat":1},{"version":"34c839eaaa6d78c8674ae2c37af2236dee6831b13db7b4ef4df3ec889a04d4f2","affectsGlobalScope":true,"impliedFormat":1},{"version":"34478567f8a80171f88f2f30808beb7da15eac0538ae91282dd33dce928d98ed","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab7d58e6161a550ff92e5aff755dc37fe896245348332cd5f1e1203479fe0ed1","affectsGlobalScope":true,"impliedFormat":1},{"version":"6bda95ea27a59a276e46043b7065b55bd4b316c25e70e29b572958fa77565d43","affectsGlobalScope":true,"impliedFormat":1},{"version":"aedb8de1abb2ff1095c153854a6df7deae4a5709c37297f9d6e9948b6806fa66","affectsGlobalScope":true,"impliedFormat":1},{"version":"a4da0551fd39b90ca7ce5f68fb55d4dc0c1396d589b612e1902f68ee090aaada","affectsGlobalScope":true,"impliedFormat":1},{"version":"11ffe3c281f375fff9ffdde8bbec7669b4dd671905509079f866f2354a788064","affectsGlobalScope":true,"impliedFormat":1},{"version":"52d1bb7ab7a3306fd0375c8bff560feed26ed676a5b0457fa8027b563aecb9a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"f1c9fe42b65437a61104e601eb298c5c859fb522b483f1bdb700eed67a16f980","impliedFormat":1},{"version":"39605640330a122a0bf7d90ecf13d9012991adb2fa4a63d04843c94394f0f96d","impliedFormat":99},{"version":"4967529644e391115ca5592184d4b63980569adf60ee685f968fd59ab1557188","impliedFormat":1},{"version":"7501fd9b2fc1fb3bc6abe499573b81db98d2954dc25df9a421973c5faaab4941","signature":"51eeac533c6eb5567faa2e43ac43d9fe25bd39581165f2f11af315bcac8efa14","impliedFormat":99},{"version":"7a73c72029575d1234a8be8d77defdac2b05e27c917543806e1697c77dbddcb4","signature":"ad9ea8a35fadce7abfe86228c0ff466dd7fe45a0aa6634b696d426d2c40e3f58","impliedFormat":99},{"version":"9f82f7dce7a1311fa6a023919337ae0cad6faefe122ca4503ae33d2e22420bc0","signature":"1ed4fa517b6642f6697e26befa2619494bca4243f77f7b8e9b1c897965d136aa","impliedFormat":99},{"version":"f7b2cc01d2477492f72e74e50997d4078a36d0c1ed9dcc18296c2741ae428de4","signature":"52ee7b65db088422f752fa8a03abd082b6e81ccd3555629a4d2996c75a3ea784","impliedFormat":99},{"version":"f841813d6e9df0f9e0180f69b4963964544886b9b59c5d75a0a4b3de45efdceb","signature":"a36a302ce150fc6aba361bf2c3f4c4f3ea6ad1a39c4a1b876df3191774974a41","impliedFormat":99},{"version":"c35f64730d5ddb935dba2b79506f5c8a851b2c40646637c7070a4033972bd73a","signature":"0700ea2ece0b6e7609f86bc93d1d4713fd3f53be3ed4d3384baddd9daff050aa","impliedFormat":99},{"version":"4017cfb925dd1318b932861fe1789154f6063bbbf4608bf47d2acc07e3887625","signature":"8b070b73bb6b42225b7c3b6625bda6664954cc3712229b18958a8943b340ae55","impliedFormat":99},{"version":"aa9efc0c0f844b992299237fc548c0d87a010e33d680ec3ef8dbfd1c7fdd4b39","signature":"5615bcac5653c419404afd7a69d3a2ea065d6d8d73d76f645dc72775da1bce2a","impliedFormat":99},{"version":"f72d2ef8589cbc9ef38bc0a1ce8e8226886673553f135c2ec7bab480a51a1b14","signature":"0949e43a56894d36a28c69ef7226bb234ea74de6bb8db9c88ccf270be3b15b52","impliedFormat":99},{"version":"12ff3a65e83059a171d45b077f870c9847c4ddffc7cb0afe9cb3d3086ec26ed9","signature":"96d6443ed4046f8418464504489b9f770f7a438b3bc7bf460fb86471d117e9a4","impliedFormat":99},{"version":"29488db8cc9b41928088c0a874a9740bee7c05b3aee6e02d8b1136aacbb3ea57","signature":"b4117081407f355734a73e4f2051edeafff14541bacaa61b2b5b74de3a6d9f91","impliedFormat":99},{"version":"cc898ec7bce7af4fb56cfc04a7bb2efd3d2b7d98ac92b74b2b4e67e7ddbf7cc2","signature":"617438c8ffeebd4b427114557e1a41f99cd439d9757e1daf742e1ce4e866e050","impliedFormat":99},{"version":"7f14dc4040d79c8027bba900d0009a387480c8fbcaef946540e7d55cb25d477d","signature":"02349a2b4e4df02eeb877449a91fa899932d9e2a7b8ef30b47cd5820af6ab06e","impliedFormat":99},{"version":"4cbe58c97ab6d95e9d3b88062a9a09fc9c4dc9173d416c2c03d3c60de633afc8","signature":"66d2b4311e142ded625c47020aba04457dc1827b2abe4a0bf5e4282b61927b41","impliedFormat":99},{"version":"4aa8cf2c03a4bef578adb195fa0048172418ddc37ef1a43521b74e659a901b3c","signature":"508df7438e5b78be306e1383ab15dbb7119fb2ca4cb13cd9cf26e0b2489afb65","impliedFormat":99},{"version":"6263b4a797ae57e4fa8f9f034db454d13b00e5f497f33d63ae48f391b3965bb2","signature":"ce5c319de9485f5bcdefb59099b3e4f23bf0f27fc8e3bbe7282f862a9f860b49","impliedFormat":99},{"version":"8ffaac172d85e0da751e89c9115923b322afd5db8b8971b7e39a5f449e0f2d72","signature":"847f3e5260297cd02349d4fdf0ade2a89e11767d04441dd7e909bd44cb7e359f","impliedFormat":99},{"version":"04f0e5540074077b5194e4e50f045b07ea1c0d4ba639f2a90c25d415be93d62a","impliedFormat":99},{"version":"05c0a6903b06e02a54a65557ce552a38890e1eae2d4924fdc63f5d8c7d48a51f","signature":"ddbb7587357abb10688237ca0e2115ff0b141bc5addf52063ba8e05c7904c183","impliedFormat":99},{"version":"8df9a1e93f38ef9e5a02ac6d69550714fa74c0aa2b2417d1e0c935270bbb2845","signature":"c23f869061db4adee9e58bfe744589b000cb97989e1c658315b86fc61aa7cb24","impliedFormat":99},{"version":"d7945a051dd621e39b53921bbf255a067fcdcdd1d2e57749dca4de8e66115251","signature":"4d806524986070b7c9f6019a46f045e083570cd6eaa6b7bb7da0d438e1ea9d9b","impliedFormat":99},{"version":"bc3158925d8f0417aea29d03f80f8bf7fc01a75f1d8c93239ee794b4b2a40fa7","signature":"0a3f05296d25399d19f2dbf65a8537022f4e8ec42258892a801664d02b66e169","impliedFormat":99},{"version":"c2a3209fd29ed0b0daa24d258b108f7b4e4ba2656a99e529ceedd4a044b2edb8","impliedFormat":99},{"version":"a0bd6bccba91b399e4e98bb50ef2064f2dd1e5566151911526368667fb27f151","impliedFormat":99},{"version":"1b38d11a73ef55b188c688ce14f14c1805409afc8052822a32fbaa5154af78fa","signature":"4e89973a43a5c0e304e3b4adacfd647525168d6128ed218841f085610b36123b","impliedFormat":99},{"version":"2fd1ade8c0b26af4e165a0ba11d3e2f0a8d5d15f001611bf63772cb15b70ebde","signature":"052cdf9abce5e9252a42c5af82cb4591f03ecb83ebbb521fb74b31e2acd0ad79","impliedFormat":99},{"version":"eb29076a307e2750601d2eaf733b7b9b17c69d0156d47a2ba14cebf1ed66b0ce","signature":"76b1d15c83a9fd9909fd81e32024727743ae506de24a1bebc60719ad93cce0db","impliedFormat":99},{"version":"7e771891adaa85b690266bc37bd6eb43bc57eecc4b54693ead36467e7369952a","impliedFormat":1},{"version":"a69c09dbea52352f479d3e7ac949fde3d17b195abe90b045d619f747b38d6d1a","impliedFormat":1},{"version":"54ba7456adb777a685250cd144115ea51379784012ba1311255b715c6bdcff2a","affectsGlobalScope":true,"impliedFormat":1},{"version":"11e2d554398d2bd460e7d06b2fa5827a297c8acfbe00b4f894a224ac0862857f","impliedFormat":1},{"version":"e193e634a99c9c1d71f1c6e4e1567a4a73584328d21ea02dd5cddbaad6693f61","affectsGlobalScope":true,"impliedFormat":1},{"version":"374ca798f244e464346f14301dc2a8b4b111af1a83b49fffef5906c338a1f922","impliedFormat":1},{"version":"5a94487653355b56018122d92392beb2e5f4a6c63ba5cef83bbe1c99775ef713","impliedFormat":1},{"version":"d5135ad93b33adcce80b18f8065087934cdc1730d63db58562edcf017e1aad9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"82408ed3e959ddc60d3e9904481b5a8dc16469928257af22a3f7d1a3bc7fd8c4","impliedFormat":1},{"version":"5450889a3b688f9da80e7c96963b2cfebc6097e8e95790a23a48558b61e6aea7","impliedFormat":1},{"version":"bb9c4ffa5e6290c6980b63c815cdd1625876dadb2efaf77edbe82984be93e55e","impliedFormat":1},{"version":"489532ff54b714f0e0939947a1c560e516d3ae93d51d639ab02e907a0e950114","impliedFormat":1},{"version":"f30bb836526d930a74593f7b0f5c1c46d10856415a8f69e5e2fc3db80371e362","impliedFormat":1},{"version":"14b5aa23c5d0ae1907bc696ac7b6915d88f7d85799cc0dc2dcf98fbce2c5a67c","impliedFormat":1},{"version":"5c439dafdc09abe4d6c260a96b822fa0ba5be7203c71a63ab1f1423cd9e838ea","impliedFormat":1},{"version":"6b526a5ec4a401ca7c26cfe6a48e641d8f30af76673bad3b06a1b4504594a960","affectsGlobalScope":true,"impliedFormat":1},{"version":"816ad2e607a96de5bcac7d437f843f5afd8957f1fa5eefa6bba8e4ed7ca8fd84","affectsGlobalScope":true,"impliedFormat":1},{"version":"80473bd0dd90ca1e166514c2dfead9d5803f9c51418864ca35abbeec6e6847e1","impliedFormat":1},{"version":"1c84b46267610a34028edfd0d035509341751262bac1062857f3c8df7aff7153","impliedFormat":1},{"version":"5eec82ac21f84d83586c59a16b9b8502d34505d1393393556682fe7e7fde9ef2","impliedFormat":1},{"version":"04eb6578a588d6a46f50299b55f30e3a04ef27d0c5a46c57d8fcc211cd530faa","impliedFormat":1},{"version":"8d3c583a07e0c37e876908c2d5da575019f689df8d9fa4c081d99119d53dba22","impliedFormat":1},{"version":"2c828a5405191d006115ab34e191b8474bc6c86ffdc401d1a9864b1b6e088a58","impliedFormat":1},{"version":"e630e5528e899219ae319e83bef54bf3bcb91b01d76861ecf881e8e614b167f0","affectsGlobalScope":true,"impliedFormat":1},{"version":"bcebb922784739bdb34c18ee51095d25a92b560c78ccd2eaacd6bd00f7443d83","impliedFormat":1},{"version":"7ee6ed878c4528215c82b664fe0cfe80e8b4da6c0d4cc80869367868774db8b1","impliedFormat":1},{"version":"b0973c3cbcdc59b37bf477731d468696ecaf442593ec51bab497a613a580fe30","impliedFormat":1},{"version":"4989e92ba5b69b182d2caaea6295af52b7dc73a4f7a2e336a676722884e7139d","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3624aed92dab6da8484280d3cb3e2f4130ec3f4ef3f8201c95144ae9e898bb6","affectsGlobalScope":true,"impliedFormat":1},{"version":"5153a2fd150e46ce57bb3f8db1318d33f6ad3261ed70ceeff92281c0608c74a3","impliedFormat":1},{"version":"210d54cd652ec0fec8c8916e4af59bb341065576ecda039842f9ffb2e908507c","impliedFormat":1},{"version":"36b03690b628eab08703d63f04eaa89c5df202e5f1edf3989f13ad389cd2c091","impliedFormat":1},{"version":"0effadd232a20498b11308058e334d3339cc5bf8c4c858393e38d9d4c0013dcf","impliedFormat":1},{"version":"25846d43937c672bab7e8195f3d881f93495df712ee901860effc109918938cc","impliedFormat":1},{"version":"fd93cee2621ff42dabe57b7be402783fd1aa69ece755bcba1e0290547ae60513","impliedFormat":1},{"version":"1b952304137851e45bc009785de89ada562d9376177c97e37702e39e60c2f1ff","impliedFormat":1},{"version":"69ee23dd0d215b09907ad30d23f88b7790c93329d1faf31d7835552a10cf7cbf","impliedFormat":1},{"version":"44b8b584a338b190a59f4f6929d072431950c7bd92ec2694821c11bce180c8a5","impliedFormat":1},{"version":"23b89798789dffbd437c0c423f5d02d11f9736aea73d6abf16db4f812ff36eda","impliedFormat":1},{"version":"09326ae5f7e3d49be5cd9ea00eb814770e71870a438faa2efd8bdd9b4db21320","impliedFormat":1},{"version":"3c4ba1dd9b12ffa284b565063108f2f031d150ea15b8fafbdc17f5d2a07251f3","affectsGlobalScope":true,"impliedFormat":1},{"version":"e10177274a35a9d07c825615340b2fcde2f610f53f3fb40269fd196b4288dda6","impliedFormat":1},{"version":"c4577fb855ca259bdbf3ea663ca73988ce5f84251a92b4aef80a1f4122b6f98e","impliedFormat":1},{"version":"3c13ef48634e7b5012fcf7e8fce7496352c2d779a7201389ca96a2a81ee4314d","impliedFormat":1},{"version":"5d0a25ec910fa36595f85a67ac992d7a53dd4064a1ba6aea1c9f14ab73a023f2","impliedFormat":1},{"version":"f0900cd5d00fe1263ff41201fb8073dbeb984397e4af3b8002a5c207a30bdc33","affectsGlobalScope":true,"impliedFormat":1},{"version":"ff07a9a03c65732ccc59b3c65bc584173da093bd563a6565411c01f5703bd3cb","affectsGlobalScope":true,"impliedFormat":1},{"version":"06d7c42d256f0ce6afe1b2b6cfbc97ab391f29dadb00dd0ae8e8f23f5bc916c3","impliedFormat":1},{"version":"ec4bd1b200670fb567920db572d6701ed42a9641d09c4ff6869768c8f81b404c","impliedFormat":1},{"version":"e59a892d87e72733e2a9ca21611b9beb52977be2696c7ba4b216cbbb9a48f5aa","impliedFormat":1},{"version":"da26af7362f53d122283bc69fed862b9a9fe27e01bc6a69d1d682e0e5a4df3e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"8a300fa9b698845a1f9c41ecbe2c5966634582a8e2020d51abcace9b55aa959e","impliedFormat":1},{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true,"impliedFormat":1},{"version":"d8d555f3d607ecaa18d55de6995ea8f206342ecc93305919eac945c7c78c78c6","impliedFormat":1},{"version":"409b21f3d0c198cc4866b941cd9303809a13230e2b9b3c1508fe61348a8b43ed","impliedFormat":1},{"version":"49afdedca00d22b171678e3cf9c47b7e0c1846fd4905a01d68f0145eb90add94","impliedFormat":1},{"version":"7a1b0fbc4287cb7513c0a10d9b53f5acc32d3ced53b2d786711901d483c4dbb4","impliedFormat":1},{"version":"8408c66a83053c21d93e73c1f6773647ccdb60fb9468f99341e389f3bfa35ad7","impliedFormat":1},{"version":"51108a0b63dc5dd793d26c1b185df7cfa1d1bf1a6e4ad9ce6f9d7ca8eb65b4ed","signature":"8a0ab25856a3fcd2c10da218932bb157fcab3ae61294c3506200f28f5d19b9c1","impliedFormat":99},{"version":"bff5e7e514980487864d34f69b6eda6f93506aff6dd9ced75f9a172ded1a71b4","impliedFormat":99},{"version":"f87022015c1924d3d60ae66c192366518af8617f7243af5af17d46a1d4d09764","signature":"9e6e67d4df1a320ac0ec7e2b58e98b332c2b4a7b2d88e1fe7463634a81f219e0","impliedFormat":99},{"version":"2c425702763ca7d738b2f0080be64d366a0818106a73c2595ed3ea51967f18c8","impliedFormat":1},{"version":"91f4e4de96699e0a21d50885d00d1dce8695f78788e3bdf40d33a299896be442","signature":"955a24e28310e9b71695b601e309957702e2da09e67f5bc5359bfae4a603e9b6","impliedFormat":99},{"version":"ac030f3c41a1797c673137478c675da6542c0676341c85f68b93fcecaaeb4778","impliedFormat":99},{"version":"afde802c7508bfa466977ea232329057a307f777c8499ee651b7abf65d65c503","signature":"de24ca8d9277f1e78c0a904ab762dca156aa55b6ae6fb2bb27c39c9193ca9b93","impliedFormat":99},{"version":"0679dbdd43d4fae7b84baf09c5299ef7fca6effba02e711fb3bcabfe4b3719ca","impliedFormat":99},{"version":"c0c2b6bb02ec7f862cb53fe5455c4333387396423b5d5e8dd2ce1a2ef294fc90","signature":"15b413ec98335b7ec0d6068d0b10ae7d4cf794b8c93cb923bed2364ff85d372c","impliedFormat":99},{"version":"1893a547b8fbe550e167f6e8c9ae7c93bda50a72121c83aac21902fd333c2274","impliedFormat":99},{"version":"d1b4b30ab8fc253dd8606c0742c2ac08d2963b98b3bbfeabc98aabb0a5775799","impliedFormat":99},{"version":"dc9806a1a14bc9f601a6e16f016ccb22b045e84d3d3ccaf49c4e05fb49b30fb7","signature":"c9b16149b0bcedd5843245a14a41729109ec43f7b9ca8dad7660d6247766c290","impliedFormat":99},{"version":"46a360e67861a830045b0a33cdb99708cb41fbe00a58def5c08716f1816701b0","signature":"e2818909ec58404f3a37a96893be135599bda8581f76ed311370fa4c4b3220a2","impliedFormat":99},{"version":"3078727fed04c123165efdb42deeac5dceaa42ac62216ca13cb809dc7e13415f","impliedFormat":1},{"version":"cc957354aa3c94c9961ebf46282cfde1e81d107fc5785a61f62c67f1dd3ac2eb","impliedFormat":1},{"version":"b4f76b34637d79cefad486127115fed843762c69512d7101b7096e1293699679","impliedFormat":1},{"version":"93de1c6dab503f053efe8d304cb522bb3a89feab8c98f307a674a4fae04773e9","impliedFormat":1},{"version":"dae3d1adc67ac3dbd1cd471889301339ec439837b5df565982345be20c8fca9a","impliedFormat":1},{"version":"b6ddf3a46ccfa4441d8be84d2e9bf3087573c48804196faedbd4a25b60631beb","impliedFormat":1},{"version":"01f7828047b5c6703d3c601473618b448f5506a88fcac852638b0715c3abf4eb","impliedFormat":1},{"version":"3896464bb7e25fceebbd9c8a0b443caaa9b68ec323f46191c36b84293c852a19","impliedFormat":1},{"version":"b8a427b9fe88504a6fb092e21adfe272d144394a2ced7f9e4adc3de7efa6e216","impliedFormat":1},{"version":"bf88ef4208a770ca39a844b182b3695df536326ea566893fdc5b8418702a331e","impliedFormat":1},{"version":"53acffbcae83dbdd20b2eeaf06a459da0f26a74e99e76fd28325b48e9e9de0d0","impliedFormat":1},{"version":"8b06ac3faeacb8484d84ddb44571d8f410697f98d7bfa86c0fda60373a9f5215","impliedFormat":1},{"version":"7eb06594824ada538b1d8b48c3925a83e7db792f47a081a62cf3e5c4e23cf0ee","impliedFormat":1},{"version":"f5638f7c2f12a9a1a57b5c41b3c1ea7db3876c003bab68e6a57afd6bcc169af0","impliedFormat":1},{"version":"6c1e688f95fcaf53b1e41c0fdadf2c1cfc96fa924eaf7f9fdb60f96deb0a4986","impliedFormat":1},{"version":"0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","impliedFormat":1},{"version":"db25694be959314fd1e868d72e567746db1db9e2001fae545d12d2a8c1bba1b8","impliedFormat":1},{"version":"43883cf3635bb1846cbdc6c363787b76227677388c74f7313e3f0edb380840fa","impliedFormat":1},{"version":"2d47012580f859dae201d2eef898a416bdae719dffc087dfd06aefe3de2f9c8d","impliedFormat":1},{"version":"3e70a7e67c2cb16f8cd49097360c0309fe9d1e3210ff9222e9dac1f8df9d4fb6","impliedFormat":1},{"version":"ab68d2a3e3e8767c3fba8f80de099a1cfc18c0de79e42cb02ae66e22dfe14a66","impliedFormat":1},{"version":"2cec1a31729b9b01e9294c33fc9425d336eff067282809761ad2e74425d6d2a5","impliedFormat":1},{"version":"2d47012580f859dae201d2eef898a416bdae719dffc087dfd06aefe3de2f9c8d","impliedFormat":1},{"version":"e10991edf67a29051eda3bf649ccc653ae1dc55b5363fa0f559f802b2017aa02","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3e604694b624fa3f83f6684185452992088f5efb2cf136b62474aa106d6f1b6","impliedFormat":1},{"version":"bc88e4049153bc4dddb4503ed7e624eb141edfa9064b3659d6c86e900fe9e621","impliedFormat":1},{"version":"2b93035328f7778d200252681c1d86285d501ed424825a18f81e4c3028aa51d9","impliedFormat":1},{"version":"2ac9c8332c5f8510b8bdd571f8271e0f39b0577714d5e95c1e79a12b2616f069","impliedFormat":1},{"version":"42c21aa963e7b86fa00801d96e88b36803188018d5ad91db2a9101bccd40b3ff","impliedFormat":1},{"version":"d31eb848cdebb4c55b4893b335a7c0cca95ad66dee13cbb7d0893810c0a9c301","impliedFormat":1},{"version":"77c1d91a129ba60b8c405f9f539e42df834afb174fe0785f89d92a2c7c16b77a","impliedFormat":1},{"version":"7a9e0a564fee396cacf706523b5aeed96e04c6b871a8bebefad78499fbffc5bc","impliedFormat":1},{"version":"906c751ef5822ec0dadcea2f0e9db64a33fb4ee926cc9f7efa38afe5d5371b2a","impliedFormat":1},{"version":"5387c049e9702f2d2d7ece1a74836a14b47fbebe9bbeb19f94c580a37c855351","impliedFormat":1},{"version":"c68391fb9efad5d99ff332c65b1606248c4e4a9f1dd9a087204242b56c7126d6","impliedFormat":1},{"version":"e9cf02252d3a0ced987d24845dcb1f11c1be5541f17e5daa44c6de2d18138d0c","impliedFormat":1},{"version":"e8b02b879754d85f48489294f99147aeccc352c760d95a6fe2b6e49cd400b2fe","impliedFormat":1},{"version":"9f6908ab3d8a86c68b86e38578afc7095114e66b2fc36a2a96e9252aac3998e0","impliedFormat":1},{"version":"0eedb2344442b143ddcd788f87096961cd8572b64f10b4afc3356aa0460171c6","impliedFormat":1},{"version":"71405cc70f183d029cc5018375f6c35117ffdaf11846c35ebf85ee3956b1b2a6","impliedFormat":1},{"version":"c68baff4d8ba346130e9753cefe2e487a16731bf17e05fdacc81e8c9a26aae9d","impliedFormat":1},{"version":"2cd15528d8bb5d0453aa339b4b52e0696e8b07e790c153831c642c3dea5ac8af","impliedFormat":1},{"version":"479d622e66283ffa9883fbc33e441f7fc928b2277ff30aacbec7b7761b4e9579","impliedFormat":1},{"version":"ade307876dc5ca267ca308d09e737b611505e015c535863f22420a11fffc1c54","impliedFormat":1},{"version":"f8cdefa3e0dee639eccbe9794b46f90291e5fd3989fcba60d2f08fde56179fb9","impliedFormat":1},{"version":"86c5a62f99aac7053976e317dbe9acb2eaf903aaf3d2e5bb1cafe5c2df7b37a8","impliedFormat":1},{"version":"2b300954ce01a8343866f737656e13243e86e5baef51bd0631b21dcef1f6e954","impliedFormat":1},{"version":"a2d409a9ffd872d6b9d78ead00baa116bbc73cfa959fce9a2f29d3227876b2a1","impliedFormat":1},{"version":"b288936f560cd71f4a6002953290de9ff8dfbfbf37f5a9391be5c83322324898","impliedFormat":1},{"version":"61178a781ef82e0ff54f9430397e71e8f365fc1e3725e0e5346f2de7b0d50dfa","impliedFormat":1},{"version":"6a6ccb37feb3aad32d9be026a3337db195979cd5727a616fc0f557e974101a54","impliedFormat":1},{"version":"c649ea79205c029a02272ef55b7ab14ada0903db26144d2205021f24727ac7a3","impliedFormat":1},{"version":"38e2b02897c6357bbcff729ef84c736727b45cc152abe95a7567caccdfad2a1d","impliedFormat":1},{"version":"d6610ea7e0b1a7686dba062a1e5544dd7d34140f4545305b7c6afaebfb348341","impliedFormat":1},{"version":"3dee35db743bdba2c8d19aece7ac049bde6fa587e195d86547c882784e6ba34c","impliedFormat":1},{"version":"b15e55c5fa977c2f25ca0b1db52cfa2d1fd4bf0baf90a8b90d4a7678ca462ff1","impliedFormat":1},{"version":"f41d30972724714763a2698ae949fbc463afb203b5fa7c4ad7e4de0871129a17","impliedFormat":1},{"version":"843dd7b6a7c6269fd43827303f5cbe65c1fecabc30b4670a50d5a15d57daeeb9","impliedFormat":1},{"version":"f06d8b8567ee9fd799bf7f806efe93b67683ef24f4dea5b23ef12edff4434d9d","impliedFormat":1},{"version":"6017384f697ff38bc3ef6a546df5b230c3c31329db84cbfe686c83bec011e2b2","impliedFormat":1},{"version":"e1a5b30d9248549ca0c0bb1d653bafae20c64c4aa5928cc4cd3017b55c2177b0","impliedFormat":1},{"version":"a593632d5878f17295bd53e1c77f27bf4c15212822f764a2bfc1702f4b413fa0","impliedFormat":1},{"version":"a868a534ba1c2ca9060b8a13b0ffbbbf78b4be7b0ff80d8c75b02773f7192c29","impliedFormat":1},{"version":"da7545aba8f54a50fde23e2ede00158dc8112560d934cee58098dfb03aae9b9d","impliedFormat":1},{"version":"34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","impliedFormat":1},{"version":"6aee496bf0ecfbf6731aa8cca32f4b6e92cdc0a444911a7d88410408a45ecc5d","impliedFormat":1},{"version":"b0d10e46cfe3f6c476b69af02eaa38e4ccc7430221ce3109ae84bb9fb8282298","impliedFormat":1},{"version":"12fe557e4c2d5ce9e11362f69a8d7c05d0588de4ae415afe8c5106da5c2772aa","impliedFormat":1},{"version":"70e9a18da08294f75bf23e46c7d69e67634c0765d355887b9b41f0d959e1426e","impliedFormat":1},{"version":"ae84439d1ae42b30ced3df38c4285f35b805be40dfc95b0647d0e59c70b11f97","impliedFormat":1}],"options":{"allowSyntheticDefaultImports":true,"composite":true,"declaration":true,"declarationMap":true,"downlevelIteration":true,"esModuleInterop":true,"importHelpers":true,"inlineSourceMap":true,"module":199,"outDir":"./dest","rootDir":"./src","strict":true,"target":7,"tsBuildInfoFile":"./.tsbuildinfo"},"fileIdsList":[[132],[132,157],[132,173],[132,157,158,159,160,161],[132,157,159],[132,139],[132,163],[103,132,139],[132,168],[132,169],[132,175,178],[132,174],[132,139,140],[102,132,139,140,141],[132,140],[86,132],[89,132],[90,95,123,132],[91,102,103,110,120,131,132],[91,92,102,110,132],[93,132],[94,95,103,111,132],[95,120,128,132],[96,98,102,110,132],[97,132],[98,99,132],[102,132],[100,102,132],[102,103,104,120,131,132],[102,103,104,117,120,123,132],[132,136],[98,105,110,120,131,132],[102,103,105,106,110,120,128,131,132],[105,107,120,128,131,132],[86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138],[102,108,132],[109,131,132],[98,102,110,120,132],[111,132],[112,132],[89,113,132],[114,130,132,136],[115,132],[116,132],[102,117,118,132],[117,119,132,134],[90,102,120,121,122,123,132],[90,120,122,132],[120,121,132],[123,132],[124,132],[102,126,127,132],[126,127,132],[95,110,120,128,132],[129,132],[110,130,132],[90,105,116,131,132],[95,132],[120,132,133],[132,134],[132,135],[90,95,102,104,113,120,131,132,134,136],[120,132,137],[132,183,222],[132,183,207,222],[132,222],[132,183],[132,183,208,222],[132,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221],[132,208,222],[132,225],[132,171,177],[132,172,176],[132,175],[56,67,82,132,145,149,151,153],[56,132],[56,72,73,74,75,132],[56,64,132],[56,65,71,132],[56,69,71,102,132],[56,62,66,67,102,132],[56,62,63,64,65,66,67,68,69,70,76,81,132],[56,64,102,132],[56,78,80,132],[56,65,77,132,136],[56,64,132,136],[56,69,79,102,132,136],[56,57,63,64,65,102,132],[56,63,64,67,69,132],[56,61,132],[56,57,132],[56,61,132,152],[56,57,59,60,90,95,132],[56,84,132,144],[56,61,82,132],[56,85,132,142,143],[56,61,82,83,132],[56,83,132,150],[56,132,146,148],[56,85,132,142,143,147],[56,61,82,83,132,136],[56,61,82,132,136],[56,57,83,132],[64],[65,71],[69,102],[62,66,67],[64,102],[65,77,136],[64,136],[65,102],[69],[61],[57],[57,90],[85],[83],[61,82]],"referencedMap":[[57,1],[159,2],[157,1],[171,1],[174,3],[173,1],[140,1],[162,4],[158,2],[160,5],[161,2],[163,6],[164,1],[165,7],[166,8],[167,6],[168,1],[169,9],[170,10],[180,11],[179,12],[181,1],[141,1],[147,13],[142,14],[143,15],[86,16],[87,16],[89,17],[90,18],[91,19],[92,20],[93,21],[94,22],[95,23],[96,24],[97,25],[98,26],[99,26],[101,27],[100,28],[102,27],[103,29],[104,30],[88,31],[138,1],[105,32],[106,33],[107,34],[139,35],[108,36],[109,37],[110,38],[111,39],[112,40],[113,41],[114,42],[115,43],[116,44],[117,45],[118,45],[119,46],[120,47],[122,48],[121,49],[123,50],[124,51],[125,1],[126,52],[127,53],[128,54],[129,55],[130,56],[131,57],[132,58],[133,59],[134,60],[135,61],[136,62],[137,63],[182,1],[207,64],[208,65],[183,66],[186,66],[205,64],[206,64],[196,64],[195,67],[193,64],[188,64],[201,64],[199,64],[203,64],[187,64],[200,64],[204,64],[189,64],[190,64],[202,64],[184,64],[191,64],[192,64],[194,64],[198,64],[209,68],[197,64],[185,64],[222,69],[221,1],[216,68],[218,70],[217,68],[210,68],[211,68],[213,68],[215,68],[219,70],[220,70],[212,70],[214,70],[223,1],[224,1],[225,1],[226,71],[58,1],[172,1],[178,72],[177,73],[176,74],[175,12],[56,1],[11,1],[13,1],[12,1],[2,1],[14,1],[15,1],[16,1],[17,1],[18,1],[19,1],[20,1],[21,1],[3,1],[4,1],[25,1],[22,1],[23,1],[24,1],[26,1],[27,1],[28,1],[5,1],[29,1],[30,1],[31,1],[32,1],[6,1],[36,1],[33,1],[34,1],[35,1],[37,1],[7,1],[38,1],[43,1],[44,1],[39,1],[40,1],[41,1],[42,1],[8,1],[48,1],[45,1],[46,1],[47,1],[49,1],[9,1],[50,1],[51,1],[52,1],[53,1],[54,1],[1,1],[10,1],[55,1],[154,75],[59,76],[76,77],[71,78],[74,79],[75,80],[72,79],[73,80],[62,76],[68,81],[63,76],[82,82],[65,78],[69,83],[64,76],[67,76],[81,84],[78,85],[77,86],[80,87],[79,86],[66,88],[70,89],[152,90],[60,91],[153,92],[61,93],[145,94],[155,95],[144,96],[84,97],[85,76],[151,98],[149,99],[148,100],[146,101],[156,102],[83,95],[150,103]],"exportedModulesMap":[[57,1],[159,2],[157,1],[171,1],[174,3],[173,1],[140,1],[162,4],[158,2],[160,5],[161,2],[163,6],[164,1],[165,7],[166,8],[167,6],[168,1],[169,9],[170,10],[180,11],[179,12],[181,1],[141,1],[147,13],[142,14],[143,15],[86,16],[87,16],[89,17],[90,18],[91,19],[92,20],[93,21],[94,22],[95,23],[96,24],[97,25],[98,26],[99,26],[101,27],[100,28],[102,27],[103,29],[104,30],[88,31],[138,1],[105,32],[106,33],[107,34],[139,35],[108,36],[109,37],[110,38],[111,39],[112,40],[113,41],[114,42],[115,43],[116,44],[117,45],[118,45],[119,46],[120,47],[122,48],[121,49],[123,50],[124,51],[125,1],[126,52],[127,53],[128,54],[129,55],[130,56],[131,57],[132,58],[133,59],[134,60],[135,61],[136,62],[137,63],[182,1],[207,64],[208,65],[183,66],[186,66],[205,64],[206,64],[196,64],[195,67],[193,64],[188,64],[201,64],[199,64],[203,64],[187,64],[200,64],[204,64],[189,64],[190,64],[202,64],[184,64],[191,64],[192,64],[194,64],[198,64],[209,68],[197,64],[185,64],[222,69],[221,1],[216,68],[218,70],[217,68],[210,68],[211,68],[213,68],[215,68],[219,70],[220,70],[212,70],[214,70],[223,1],[224,1],[225,1],[226,71],[58,1],[172,1],[178,72],[177,73],[176,74],[175,12],[56,1],[11,1],[13,1],[12,1],[2,1],[14,1],[15,1],[16,1],[17,1],[18,1],[19,1],[20,1],[21,1],[3,1],[4,1],[25,1],[22,1],[23,1],[24,1],[26,1],[27,1],[28,1],[5,1],[29,1],[30,1],[31,1],[32,1],[6,1],[36,1],[33,1],[34,1],[35,1],[37,1],[7,1],[38,1],[43,1],[44,1],[39,1],[40,1],[41,1],[42,1],[8,1],[48,1],[45,1],[46,1],[47,1],[49,1],[9,1],[50,1],[51,1],[52,1],[53,1],[54,1],[1,1],[10,1],[55,1],[154,75],[76,77],[71,104],[74,105],[75,106],[72,105],[73,106],[68,107],[82,82],[65,104],[69,108],[81,84],[78,109],[77,110],[80,106],[79,110],[66,111],[70,112],[152,113],[60,114],[153,92],[61,115],[145,94],[155,113],[144,116],[84,117],[151,98],[149,99],[148,116],[146,117],[156,113],[83,118],[150,117]],"semanticDiagnosticsPerFile":[57,159,157,171,174,173,140,162,158,160,161,163,164,165,166,167,168,169,170,180,179,181,141,147,142,143,86,87,89,90,91,92,93,94,95,96,97,98,99,101,100,102,103,104,88,138,105,106,107,139,108,109,110,111,112,113,114,115,116,117,118,119,120,122,121,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,182,207,208,183,186,205,206,196,195,193,188,201,199,203,187,200,204,189,190,202,184,191,192,194,198,209,197,185,222,221,216,218,217,210,211,213,215,219,220,212,214,223,224,225,226,58,172,178,177,176,175,56,11,13,12,2,14,15,16,17,18,19,20,21,3,4,25,22,23,24,26,27,28,5,29,30,31,32,6,36,33,34,35,37,7,38,43,44,39,40,41,42,8,48,45,46,47,49,9,50,51,52,53,54,1,10,55,154,59,76,71,74,75,72,73,62,68,63,82,65,69,64,67,81,78,77,80,79,66,70,152,60,153,61,145,155,144,84,85,151,149,148,146,156,83,150],"latestChangedDtsFile":"./dest/worker/node/start_node_module.d.ts"},"version":"4.9.5"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/Dockerfile b/yarn-project/.yalc/@aztec/wasm/Dockerfile new file mode 100644 index 000000000000..ff060f58035e --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/Dockerfile @@ -0,0 +1,14 @@ +FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-base AS builder + +COPY wasm wasm +WORKDIR /usr/src/yarn-project/wasm +RUN yarn build && yarn formatting && yarn test + +# Prune dev dependencies. See comment in base image. +RUN yarn cache clean +RUN yarn workspaces focus --production > /dev/null + +FROM alpine:latest +COPY --from=builder /usr/src/yarn-project/wasm /usr/src/yarn-project/wasm +WORKDIR /usr/src/yarn-project/wasm +ENTRYPOINT ["yarn"] \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/README.md b/yarn-project/.yalc/@aztec/wasm/README.md new file mode 100644 index 000000000000..b15e77562881 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/README.md @@ -0,0 +1,6 @@ +# wasm + +Functionality to: + +1. Call WebAssembly functions +2. Create asynchronous workers that host webassembly. diff --git a/yarn-project/.yalc/@aztec/wasm/dest/index.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/index.d.ts new file mode 100644 index 000000000000..a363b56ac218 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/index.d.ts @@ -0,0 +1,8 @@ +export { WebDataStore } from './worker/browser/index.js'; +export { NodeDataStore } from './worker/node/index.js'; +export { WasmWorker, WorkerPool } from './worker/index.js'; +export { WasmModule } from './wasm/index.js'; +export { AsyncCallState, AsyncFnState } from './wasm/index.js'; +export { DispatchMsg, WorkerListener, TransportServer, NodeListener } from './transport/index.js'; +export { Transfer, isTransferDescriptor } from './transport/interface/transferable.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/index.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/index.d.ts.map new file mode 100644 index 000000000000..a6a4ba638578 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAClG,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/index.js b/yarn-project/.yalc/@aztec/wasm/dest/index.js new file mode 100644 index 000000000000..6f596b657159 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/index.js @@ -0,0 +1,8 @@ +export { WebDataStore } from './worker/browser/index.js'; +export { NodeDataStore } from './worker/node/index.js'; +export { WorkerPool } from './worker/index.js'; +export { WasmModule } from './wasm/index.js'; +export { AsyncCallState } from './wasm/index.js'; +export { WorkerListener, TransportServer, NodeListener } from './transport/index.js'; +export { Transfer, isTransferDescriptor } from './transport/interface/transferable.js'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQWMsVUFBVSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDM0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxjQUFjLEVBQWdCLE1BQU0saUJBQWlCLENBQUM7QUFDL0QsT0FBTyxFQUFlLGNBQWMsRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEcsT0FBTyxFQUFFLFFBQVEsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/memory_fifo.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/memory_fifo.d.ts new file mode 100644 index 000000000000..de592d842b4b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/memory_fifo.d.ts @@ -0,0 +1,46 @@ +/** + * A simple fifo queue. It can grow unbounded. It can have multiple producers and consumers. + * Putting an item onto the queue always succeeds, unless either end() or cancel() has been called in which case + * the item being pushed is simply discarded. + */ +export declare class MemoryFifo { + private waiting; + private items; + private flushing; + /** + * Length of queue. + * @returns integer. + */ + length(): number; + /** + * Returns next item within the queue, or blocks until and item has been put into the queue. + * If given a timeout, the promise will reject if no item is received after `timeout` seconds. + * If the queue is flushing, `null` is returned. + * @param timeout - In seconds. + * @returns Promise of result. + */ + get(timeout?: number): Promise; + /** + * Put an item onto back of the queue. + * @param item - The item to enqueue. + */ + put(item: T): void; + /** + * Once ended, no further items are added to queue. Consumers will consume remaining items within the queue. + * The queue is not reusable after calling `end()`. + * Any consumers waiting for an item receive null. + */ + end(): void; + /** + * Once cancelled, all items are discarded from the queue, and no further items are added to the queue. + * The queue is not reusable after calling `cancel()`. + * Any consumers waiting for an item receive null. + */ + cancel(): void; + /** + * Helper method that can be used to continously consume and process items on the queue. + * @param handler - The item handler function. + */ + process(handler: (item: T) => Promise): Promise; +} +//# sourceMappingURL=memory_fifo.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/memory_fifo.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/memory_fifo.d.ts.map new file mode 100644 index 000000000000..9bb1710ce16e --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/memory_fifo.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"memory_fifo.d.ts","sourceRoot":"","sources":["../src/memory_fifo.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,qBAAa,UAAU,CAAC,CAAC;IACvB,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;OAGG;IACI,MAAM;IAIb;;;;;;OAMG;IACI,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAyB/C;;;OAGG;IACI,GAAG,CAAC,IAAI,EAAE,CAAC;IAUlB;;;;OAIG;IACI,GAAG;IAKV;;;;OAIG;IACI,MAAM;IAMb;;;OAGG;IACU,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC;CAazD"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/memory_fifo.js b/yarn-project/.yalc/@aztec/wasm/dest/memory_fifo.js new file mode 100644 index 000000000000..f742e3a773c9 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/memory_fifo.js @@ -0,0 +1,101 @@ +// TODO should come from a dependency +/** + * A simple fifo queue. It can grow unbounded. It can have multiple producers and consumers. + * Putting an item onto the queue always succeeds, unless either end() or cancel() has been called in which case + * the item being pushed is simply discarded. + */ +export class MemoryFifo { + constructor() { + this.waiting = []; + this.items = []; + this.flushing = false; + } + /** + * Length of queue. + * @returns integer. + */ + length() { + return this.items.length; + } + /** + * Returns next item within the queue, or blocks until and item has been put into the queue. + * If given a timeout, the promise will reject if no item is received after `timeout` seconds. + * If the queue is flushing, `null` is returned. + * @param timeout - In seconds. + * @returns Promise of result. + */ + get(timeout) { + if (this.items.length) { + return Promise.resolve(this.items.shift()); + } + if (this.items.length === 0 && this.flushing) { + return Promise.resolve(null); + } + return new Promise((resolve, reject) => { + this.waiting.push(resolve); + if (timeout) { + setTimeout(() => { + const index = this.waiting.findIndex(r => r === resolve); + if (index > -1) { + this.waiting.splice(index, 1); + const err = new Error('Timeout getting item from queue.'); + reject(err); + } + }, timeout * 1000); + } + }); + } + /** + * Put an item onto back of the queue. + * @param item - The item to enqueue. + */ + put(item) { + if (this.flushing) { + return; + } + else if (this.waiting.length) { + this.waiting.shift()(item); + } + else { + this.items.push(item); + } + } + /** + * Once ended, no further items are added to queue. Consumers will consume remaining items within the queue. + * The queue is not reusable after calling `end()`. + * Any consumers waiting for an item receive null. + */ + end() { + this.flushing = true; + this.waiting.forEach(resolve => resolve(null)); + } + /** + * Once cancelled, all items are discarded from the queue, and no further items are added to the queue. + * The queue is not reusable after calling `cancel()`. + * Any consumers waiting for an item receive null. + */ + cancel() { + this.flushing = true; + this.items = []; + this.waiting.forEach(resolve => resolve(null)); + } + /** + * Helper method that can be used to continously consume and process items on the queue. + * @param handler - The item handler function. + */ + async process(handler) { + try { + while (true) { + const item = await this.get(); + if (item === null) { + break; + } + await handler(item); + } + } + catch (err) { + console.error('Queue handler exception:', err); + } + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5X2ZpZm8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbWVtb3J5X2ZpZm8udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEscUNBQXFDO0FBQ3JDOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQUF2QjtRQUNVLFlBQU8sR0FBaUMsRUFBRSxDQUFDO1FBQzNDLFVBQUssR0FBUSxFQUFFLENBQUM7UUFDaEIsYUFBUSxHQUFHLEtBQUssQ0FBQztJQThGM0IsQ0FBQztJQTVGQzs7O09BR0c7SUFDSSxNQUFNO1FBQ1gsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUMzQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksR0FBRyxDQUFDLE9BQWdCO1FBQ3pCLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUU7WUFDckIsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFHLENBQUMsQ0FBQztTQUM3QztRQUVELElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDNUMsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQzlCO1FBRUQsT0FBTyxJQUFJLE9BQU8sQ0FBVyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUMvQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUUzQixJQUFJLE9BQU8sRUFBRTtnQkFDWCxVQUFVLENBQUMsR0FBRyxFQUFFO29CQUNkLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLE9BQU8sQ0FBQyxDQUFDO29CQUN6RCxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsRUFBRTt3QkFDZCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7d0JBQzlCLE1BQU0sR0FBRyxHQUFHLElBQUksS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUM7d0JBQzFELE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztxQkFDYjtnQkFDSCxDQUFDLEVBQUUsT0FBTyxHQUFHLElBQUksQ0FBQyxDQUFDO2FBQ3BCO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksR0FBRyxDQUFDLElBQU87UUFDaEIsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2pCLE9BQU87U0FDUjthQUFNLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUU7WUFDOUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUM3QjthQUFNO1lBQ0wsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDdkI7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLEdBQUc7UUFDUixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNyQixJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksTUFBTTtRQUNYLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBbUM7UUFDdEQsSUFBSTtZQUNGLE9BQU8sSUFBSSxFQUFFO2dCQUNYLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUM5QixJQUFJLElBQUksS0FBSyxJQUFJLEVBQUU7b0JBQ2pCLE1BQU07aUJBQ1A7Z0JBQ0QsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDckI7U0FDRjtRQUFDLE9BQU8sR0FBRyxFQUFFO1lBQ1osT0FBTyxDQUFDLEtBQUssQ0FBQywwQkFBMEIsRUFBRSxHQUFHLENBQUMsQ0FBQztTQUNoRDtJQUNILENBQUM7Q0FDRiJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/index.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/index.d.ts new file mode 100644 index 000000000000..9432a480ed8e --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/index.d.ts @@ -0,0 +1,5 @@ +export * from './worker_connector.js'; +export * from './worker_listener.js'; +export * from './shared_worker_connector.js'; +export * from './shared_worker_listener.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/index.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/index.d.ts.map new file mode 100644 index 000000000000..381d5165ffc4 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transport/browser/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/index.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/index.js new file mode 100644 index 000000000000..d0103503cb4e --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/index.js @@ -0,0 +1,5 @@ +export * from './worker_connector.js'; +export * from './worker_listener.js'; +export * from './shared_worker_connector.js'; +export * from './shared_worker_listener.js'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHJhbnNwb3J0L2Jyb3dzZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLHNCQUFzQixDQUFDO0FBQ3JDLGNBQWMsOEJBQThCLENBQUM7QUFDN0MsY0FBYyw2QkFBNkIsQ0FBQyJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/message_port_socket.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/message_port_socket.d.ts new file mode 100644 index 000000000000..65fcce26e3e3 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/message_port_socket.d.ts @@ -0,0 +1,28 @@ +import { Socket } from '../interface/socket.js'; +/** + * An implementation of a TransportSocket using MessagePorts. + */ +export declare class MessagePortSocket implements Socket { + private port; + /** + * Create a MessagePortSocket. + * @param port - MessagePort object to wrap. + */ + constructor(port: MessagePort); + /** + * Send a message over our message port. + * @param msg - The message. + * @param transfer - Objects to transfer ownership of. + */ + send(msg: any, transfer?: Transferable[]): Promise; + /** + * Add a message handler. + * @param cb - The handler. + */ + registerHandler(cb: (msg: any) => any): void; + /** + * Close this message port. + */ + close(): void; +} +//# sourceMappingURL=message_port_socket.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/message_port_socket.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/message_port_socket.d.ts.map new file mode 100644 index 000000000000..077d4623f515 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/message_port_socket.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"message_port_socket.d.ts","sourceRoot":"","sources":["../../../src/transport/browser/message_port_socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD;;GAEG;AACH,qBAAa,iBAAkB,YAAW,MAAM;IAKlC,OAAO,CAAC,IAAI;IAJxB;;;OAGG;gBACiB,IAAI,EAAE,WAAW;IAErC;;;;OAIG;IACH,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,GAAE,YAAY,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;;OAGG;IACH,eAAe,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,GAAG,IAAI;IAI5C;;OAEG;IACH,KAAK;CAKN"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/message_port_socket.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/message_port_socket.js new file mode 100644 index 000000000000..03387a31f8c9 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/message_port_socket.js @@ -0,0 +1,37 @@ +/** + * An implementation of a TransportSocket using MessagePorts. + */ +export class MessagePortSocket { + /** + * Create a MessagePortSocket. + * @param port - MessagePort object to wrap. + */ + constructor(port) { + this.port = port; + } + /** + * Send a message over our message port. + * @param msg - The message. + * @param transfer - Objects to transfer ownership of. + */ + send(msg, transfer = []) { + this.port.postMessage(msg, transfer); + return Promise.resolve(); + } + /** + * Add a message handler. + * @param cb - The handler. + */ + registerHandler(cb) { + this.port.onmessage = event => cb(event.data); + } + /** + * Close this message port. + */ + close() { + void this.send(undefined); + this.port.onmessage = null; + this.port.close(); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVzc2FnZV9wb3J0X3NvY2tldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90cmFuc3BvcnQvYnJvd3Nlci9tZXNzYWdlX3BvcnRfc29ja2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQUM1Qjs7O09BR0c7SUFDSCxZQUFvQixJQUFpQjtRQUFqQixTQUFJLEdBQUosSUFBSSxDQUFhO0lBQUcsQ0FBQztJQUV6Qzs7OztPQUlHO0lBQ0gsSUFBSSxDQUFDLEdBQVEsRUFBRSxXQUEyQixFQUFFO1FBQzFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNyQyxPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsZUFBZSxDQUFDLEVBQXFCO1FBQ25DLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzFCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3BCLENBQUM7Q0FDRiJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_connector.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_connector.d.ts new file mode 100644 index 000000000000..032f9df12b35 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_connector.d.ts @@ -0,0 +1,19 @@ +import { Connector } from '../interface/connector.js'; +import { MessagePortSocket } from './message_port_socket.js'; +/** + * Connector implementation which wraps a SharedWorker. + */ +export declare class SharedWorkerConnector implements Connector { + private worker; + /** + * Create a SharedWorkerConnector. + * @param worker - A shared worker. + */ + constructor(worker: SharedWorker); + /** + * Create a Socket implementation with our mesage port. + * @returns The socket. + */ + createSocket(): Promise; +} +//# sourceMappingURL=shared_worker_connector.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_connector.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_connector.d.ts.map new file mode 100644 index 000000000000..b745dd62aed4 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_connector.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"shared_worker_connector.d.ts","sourceRoot":"","sources":["../../../src/transport/browser/shared_worker_connector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;GAEG;AACH,qBAAa,qBAAsB,YAAW,SAAS;IAKzC,OAAO,CAAC,MAAM;IAJ1B;;;OAGG;gBACiB,MAAM,EAAE,YAAY;IAExC;;;OAGG;IACH,YAAY;CAGb"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_connector.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_connector.js new file mode 100644 index 000000000000..fa8778b40a91 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_connector.js @@ -0,0 +1,21 @@ +import { MessagePortSocket } from './message_port_socket.js'; +/** + * Connector implementation which wraps a SharedWorker. + */ +export class SharedWorkerConnector { + /** + * Create a SharedWorkerConnector. + * @param worker - A shared worker. + */ + constructor(worker) { + this.worker = worker; + } + /** + * Create a Socket implementation with our mesage port. + * @returns The socket. + */ + createSocket() { + return Promise.resolve(new MessagePortSocket(this.worker.port)); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkX3dvcmtlcl9jb25uZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHJhbnNwb3J0L2Jyb3dzZXIvc2hhcmVkX3dvcmtlcl9jb25uZWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFN0Q7O0dBRUc7QUFDSCxNQUFNLE9BQU8scUJBQXFCO0lBQ2hDOzs7T0FHRztJQUNILFlBQW9CLE1BQW9CO1FBQXBCLFdBQU0sR0FBTixNQUFNLENBQWM7SUFBRyxDQUFDO0lBRTVDOzs7T0FHRztJQUNILFlBQVk7UUFDVixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbEUsQ0FBQztDQUNGIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_listener.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_listener.d.ts new file mode 100644 index 000000000000..e6e93d9b214b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_listener.d.ts @@ -0,0 +1,38 @@ +/// +import EventEmitter from 'events'; +import { Listener } from '../interface/listener.js'; +/** + * See https://developer.mozilla.org/en-US/docs/Web/API/SharedWorkerGlobalScope. + */ +declare interface SharedWorkerGlobalScope { + /** + * Fired on shared workers when a new client connects. + */ + onconnect: any; +} +/** + * Listens for connections to a shared worker. + */ +export declare class SharedWorkerListener extends EventEmitter implements Listener { + private worker; + /** + * + * @param worker + */ + constructor(worker: SharedWorkerGlobalScope); + /** + * + */ + open(): void; + /** + * + */ + close(): void; + /** + * + * @param event + */ + private handleMessageEvent; +} +export {}; +//# sourceMappingURL=shared_worker_listener.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_listener.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_listener.d.ts.map new file mode 100644 index 000000000000..72ac8c251e3f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_listener.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"shared_worker_listener.d.ts","sourceRoot":"","sources":["../../../src/transport/browser/shared_worker_listener.ts"],"names":[],"mappings":";AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD;;GAEG;AACH,OAAO,WAAW,uBAAuB;IACvC;;OAEG;IACH,SAAS,EAAE,GAAG,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,YAAa,YAAW,QAAQ;IAK5D,OAAO,CAAC,MAAM;IAJ1B;;;OAGG;gBACiB,MAAM,EAAE,uBAAuB;IAInD;;OAEG;IACH,IAAI;IAIJ;;OAEG;IACH,KAAK;IAIL;;;OAGG;IACH,OAAO,CAAC,kBAAkB,CAMxB;CACH"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_listener.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_listener.js new file mode 100644 index 000000000000..e0cec42374b5 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/shared_worker_listener.js @@ -0,0 +1,39 @@ +import EventEmitter from 'events'; +import { MessagePortSocket } from './message_port_socket.js'; +/** + * Listens for connections to a shared worker. + */ +export class SharedWorkerListener extends EventEmitter { + /** + * + * @param worker + */ + constructor(worker) { + super(); + this.worker = worker; + /** + * + * @param event + */ + this.handleMessageEvent = (event) => { + const [port] = event.ports; + if (!port) { + return; + } + this.emit('new_socket', new MessagePortSocket(port)); + }; + } + /** + * + */ + open() { + this.worker.onconnect = this.handleMessageEvent; + } + /** + * + */ + close() { + this.worker.onconnect = () => { }; + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkX3dvcmtlcl9saXN0ZW5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90cmFuc3BvcnQvYnJvd3Nlci9zaGFyZWRfd29ya2VyX2xpc3RlbmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sWUFBWSxNQUFNLFFBQVEsQ0FBQztBQUVsQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQVk3RDs7R0FFRztBQUNILE1BQU0sT0FBTyxvQkFBcUIsU0FBUSxZQUFZO0lBQ3BEOzs7T0FHRztJQUNILFlBQW9CLE1BQStCO1FBQ2pELEtBQUssRUFBRSxDQUFDO1FBRFUsV0FBTSxHQUFOLE1BQU0sQ0FBeUI7UUFrQm5EOzs7V0FHRztRQUNLLHVCQUFrQixHQUFHLENBQUMsS0FBbUIsRUFBRSxFQUFFO1lBQ25ELE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO1lBQzNCLElBQUksQ0FBQyxJQUFJLEVBQUU7Z0JBQ1QsT0FBTzthQUNSO1lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3ZELENBQUMsQ0FBQztJQTFCRixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJO1FBQ0YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDO0lBQ2xELENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUs7UUFDSCxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsR0FBRyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7SUFDbkMsQ0FBQztDQWFGIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_connector.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_connector.d.ts new file mode 100644 index 000000000000..a7eba90c1acc --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_connector.d.ts @@ -0,0 +1,18 @@ +import { Connector } from '../interface/connector.js'; +import { MessagePortSocket } from './message_port_socket.js'; +/** + * + */ +export declare class WorkerConnector implements Connector { + private worker; + /** + * + * @param worker + */ + constructor(worker: Worker); + /** + * + */ + createSocket(): Promise; +} +//# sourceMappingURL=worker_connector.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_connector.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_connector.d.ts.map new file mode 100644 index 000000000000..a0af81a87760 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_connector.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"worker_connector.d.ts","sourceRoot":"","sources":["../../../src/transport/browser/worker_connector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;GAEG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAKnC,OAAO,CAAC,MAAM;IAJ1B;;;OAGG;gBACiB,MAAM,EAAE,MAAM;IAElC;;OAEG;IACH,YAAY;CAKb"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_connector.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_connector.js new file mode 100644 index 000000000000..4faae6403cf0 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_connector.js @@ -0,0 +1,22 @@ +import { MessagePortSocket } from './message_port_socket.js'; +/** + * + */ +export class WorkerConnector { + /** + * + * @param worker + */ + constructor(worker) { + this.worker = worker; + } + /** + * + */ + createSocket() { + const channel = new MessageChannel(); + this.worker.postMessage('', [channel.port2]); + return Promise.resolve(new MessagePortSocket(channel.port1)); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2VyX2Nvbm5lY3Rvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90cmFuc3BvcnQvYnJvd3Nlci93b3JrZXJfY29ubmVjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRTdEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFDMUI7OztPQUdHO0lBQ0gsWUFBb0IsTUFBYztRQUFkLFdBQU0sR0FBTixNQUFNLENBQVE7SUFBRyxDQUFDO0lBRXRDOztPQUVHO0lBQ0gsWUFBWTtRQUNWLE1BQU0sT0FBTyxHQUFHLElBQUksY0FBYyxFQUFFLENBQUM7UUFDckMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDN0MsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksaUJBQWlCLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDL0QsQ0FBQztDQUNGIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_listener.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_listener.d.ts new file mode 100644 index 000000000000..135a82ed2c41 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_listener.d.ts @@ -0,0 +1,38 @@ +/// +import EventEmitter from 'events'; +import { Listener } from '../interface/listener.js'; +/** + * + */ +declare interface DedicatedWorkerGlobalScope { + /** + * + */ + onmessage: any; +} +/** + * + */ +export declare class WorkerListener extends EventEmitter implements Listener { + private worker; + /** + * + * @param worker + */ + constructor(worker: DedicatedWorkerGlobalScope); + /** + * + */ + open(): void; + /** + * + */ + close(): void; + /** + * + * @param event + */ + private handleMessageEvent; +} +export {}; +//# sourceMappingURL=worker_listener.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_listener.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_listener.d.ts.map new file mode 100644 index 000000000000..778536fc69b7 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_listener.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"worker_listener.d.ts","sourceRoot":"","sources":["../../../src/transport/browser/worker_listener.ts"],"names":[],"mappings":";AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD;;GAEG;AACH,OAAO,WAAW,0BAA0B;IAC1C;;OAEG;IACH,SAAS,EAAE,GAAG,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,YAAa,YAAW,QAAQ;IAKtD,OAAO,CAAC,MAAM;IAJ1B;;;OAGG;gBACiB,MAAM,EAAE,0BAA0B;IAItD;;OAEG;IACH,IAAI;IAIJ;;OAEG;IACH,KAAK;IAIL;;;OAGG;IACH,OAAO,CAAC,kBAAkB,CAMxB;CACH"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_listener.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_listener.js new file mode 100644 index 000000000000..75430d08d97a --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/browser/worker_listener.js @@ -0,0 +1,39 @@ +import EventEmitter from 'events'; +import { MessagePortSocket } from './message_port_socket.js'; +/** + * + */ +export class WorkerListener extends EventEmitter { + /** + * + * @param worker + */ + constructor(worker) { + super(); + this.worker = worker; + /** + * + * @param event + */ + this.handleMessageEvent = (event) => { + const [port] = event.ports; + if (!port) { + return; + } + this.emit('new_socket', new MessagePortSocket(port)); + }; + } + /** + * + */ + open() { + this.worker.onmessage = this.handleMessageEvent; + } + /** + * + */ + close() { + this.worker.onmessage = () => { }; + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2VyX2xpc3RlbmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC9icm93c2VyL3dvcmtlcl9saXN0ZW5lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLFlBQVksTUFBTSxRQUFRLENBQUM7QUFFbEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFZN0Q7O0dBRUc7QUFDSCxNQUFNLE9BQU8sY0FBZSxTQUFRLFlBQVk7SUFDOUM7OztPQUdHO0lBQ0gsWUFBb0IsTUFBa0M7UUFDcEQsS0FBSyxFQUFFLENBQUM7UUFEVSxXQUFNLEdBQU4sTUFBTSxDQUE0QjtRQWtCdEQ7OztXQUdHO1FBQ0ssdUJBQWtCLEdBQUcsQ0FBQyxLQUFtQixFQUFFLEVBQUU7WUFDbkQsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFDM0IsSUFBSSxDQUFDLElBQUksRUFBRTtnQkFDVCxPQUFPO2FBQ1I7WUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDdkQsQ0FBQyxDQUFDO0lBMUJGLENBQUM7SUFFRDs7T0FFRztJQUNILElBQUk7UUFDRixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDbEQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxHQUFHLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQztJQUNuQyxDQUFDO0NBYUYifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_fn.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_fn.d.ts new file mode 100644 index 000000000000..fdb3921facf6 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_fn.d.ts @@ -0,0 +1,21 @@ +/** + * + */ +export interface DispatchMsg { + /** + * + */ + fn: string; + /** + * + */ + args: any[]; +} +/** + * + */ +export declare function createDispatchFn(targetFn: () => any, debug?: { + (...data: any[]): void; + (message?: any, ...optionalParams: any[]): void; +}): ({ fn, args }: DispatchMsg) => Promise; +//# sourceMappingURL=create_dispatch_fn.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_fn.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_fn.d.ts.map new file mode 100644 index 000000000000..a8e465a9c16e --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_fn.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"create_dispatch_fn.d.ts","sourceRoot":"","sources":["../../../src/transport/dispatch/create_dispatch_fn.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,IAAI,EAAE,GAAG,EAAE,CAAC;CACb;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,EAAE,KAAK;;;CAAgB,kBAC7C,WAAW,kBAKxC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_fn.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_fn.js new file mode 100644 index 000000000000..09b635703d4b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_fn.js @@ -0,0 +1,11 @@ +/** + * + */ +export function createDispatchFn(targetFn, debug = console.error) { + return async ({ fn, args }) => { + const target = targetFn(); + debug(`dispatching to ${target}: ${fn}`, args); + return await target[fn](...args); + }; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlX2Rpc3BhdGNoX2ZuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC9kaXNwYXRjaC9jcmVhdGVfZGlzcGF0Y2hfZm4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBY0E7O0dBRUc7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsUUFBbUIsRUFBRSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUs7SUFDekUsT0FBTyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFlLEVBQUUsRUFBRTtRQUN6QyxNQUFNLE1BQU0sR0FBRyxRQUFRLEVBQUUsQ0FBQztRQUMxQixLQUFLLENBQUMsa0JBQWtCLE1BQU0sS0FBSyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMvQyxPQUFPLE1BQU0sTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbkMsQ0FBQyxDQUFDO0FBQ0osQ0FBQyJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_proxy.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_proxy.d.ts new file mode 100644 index 000000000000..27edab62dc3b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_proxy.d.ts @@ -0,0 +1,50 @@ +import { DispatchMsg } from './create_dispatch_fn.js'; +import { TransportClient } from '../transport_client.js'; +import { TransferDescriptor } from '../interface/transferable.js'; +type FilterOutAttributes = { + [Key in keyof Base]: Base[Key] extends (...args: any) => any ? Base[Key] : never; +}; +type PromisifyFunction any> = (...args: Parameters) => Promise>; +type Promisify any; +}> = { + [Key in keyof Base]: ReturnType extends Promise ? Base[Key] : PromisifyFunction; +}; +/** + * Unpack transfer types + */ +type TransferTypes = { + [Index in keyof Tuple]: Tuple[Index] | (Tuple[Index] extends Transferable ? TransferDescriptor : never); +}; +/** + * Annoying: https://github.com/microsoft/TypeScript/issues/29919 + * There's a bug that means we can't map over the tuple or function parameter types to make them transferrable, if + * we use the Parameters builtin, and then try to map. + * So instead we inline the Parameters builtin and apply the TransferTypes to the parameters within the inline. + * Once the above is fixed we could in theory just do: + * + * type MakeFunctionTransferrable any> = ( + * ...args: TransferTypes> + * ) => ReturnType;. + */ +type MakeFunctionTransferrable any> = (...args: TFunction extends (...args: infer P) => any ? TransferTypes

: never) => ReturnType; +type Transferrable any; +}> = { + [Key in keyof Base]: MakeFunctionTransferrable; +}; +export type Proxify = Promisify>>; +export declare function createDispatchProxyFromFn(class_: { + new (...args: any[]): T; +}, requestFn: (fn: string) => (...args: any[]) => Promise): Proxify; +/** + * Create a proxy object of our class T that uses transportClient + * @param class_ - Our class T. + * @param transportClient - The transport infrastructure. + * @returns A proxy over T. + */ +export declare function createDispatchProxy(class_: { + new (...args: any[]): T; +}, transportClient: TransportClient): Proxify; +export {}; +//# sourceMappingURL=create_dispatch_proxy.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_proxy.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_proxy.d.ts.map new file mode 100644 index 000000000000..8e5e12339be5 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_proxy.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"create_dispatch_proxy.d.ts","sourceRoot":"","sources":["../../../src/transport/dispatch/create_dispatch_proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAwB,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAExF,KAAK,mBAAmB,CAAC,IAAI,IAAI;KAC9B,GAAG,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK;CACjF,CAAC;AAEF,KAAK,iBAAiB,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7G,KAAK,SAAS,CAAC,IAAI,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,CAAA;CAAE,IAAI;KACrE,GAAG,IAAI,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;CAC3G,CAAC;AAEF;;GAEG;AACH,KAAK,aAAa,CAAC,KAAK,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,IAAI;KAChD,KAAK,IAAI,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC;CACtH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,KAAK,yBAAyB,CAAC,SAAS,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CACxE,GAAG,IAAI,EAAE,SAAS,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,KAC5E,UAAU,CAAC,SAAS,CAAC,CAAC;AAE3B,KAAK,aAAa,CAAC,IAAI,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;CAAE,IAAI;KAC3E,GAAG,IAAI,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,SAAS,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE1E,wBAAgB,yBAAyB,CAAC,CAAC,EACzC,MAAM,EAAE;IAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,EACnC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,GAC1D,OAAO,CAAC,CAAC,CAAC,CASZ;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,MAAM,EAAE;IAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,EACnC,eAAe,EAAE,eAAe,CAAC,WAAW,CAAC,GAC5C,OAAO,CAAC,CAAC,CAAC,CAqBZ"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_proxy.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_proxy.js new file mode 100644 index 000000000000..49833dfc7480 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/create_dispatch_proxy.js @@ -0,0 +1,38 @@ +import { EventEmitter } from 'events'; +import { isTransferDescriptor } from '../interface/transferable.js'; +export function createDispatchProxyFromFn(class_, requestFn) { + const proxy = class_.prototype instanceof EventEmitter ? new EventEmitter() : {}; + for (const fn of Object.getOwnPropertyNames(class_.prototype)) { + if (fn === 'constructor') { + continue; + } + proxy[fn] = requestFn(fn); + } + return proxy; +} +/** + * Create a proxy object of our class T that uses transportClient + * @param class_ - Our class T. + * @param transportClient - The transport infrastructure. + * @returns A proxy over T. + */ +export function createDispatchProxy(class_, transportClient) { + // Create a proxy of class_ that passes along methods over our transportClient + const proxy = createDispatchProxyFromFn(class_, (fn) => (...args) => { + // Pass our proxied function name and arguments over our transport client + const transfer = args.reduce((acc, a) => (isTransferDescriptor(a) ? [...acc, ...a.transferables] : acc), []); + args = args.map(a => (isTransferDescriptor(a) ? a.send : a)); + return transportClient.request({ fn, args }, transfer); + }); + if (proxy instanceof EventEmitter) { + // Handle proxied 'emit' calls if our proxy object is an EventEmitter + transportClient.on('event_msg', ({ fn, args }) => { + if (fn === 'emit') { + const [eventName, ...restArgs] = args; + proxy.emit(eventName, ...restArgs); + } + }); + } + return proxy; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlX2Rpc3BhdGNoX3Byb3h5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC9kaXNwYXRjaC9jcmVhdGVfZGlzcGF0Y2hfcHJveHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUN0QyxPQUFPLEVBQUUsb0JBQW9CLEVBQXNCLE1BQU0sOEJBQThCLENBQUM7QUF3Q3hGLE1BQU0sVUFBVSx5QkFBeUIsQ0FDdkMsTUFBbUMsRUFDbkMsU0FBMkQ7SUFFM0QsTUFBTSxLQUFLLEdBQVEsTUFBTSxDQUFDLFNBQVMsWUFBWSxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUN0RixLQUFLLE1BQU0sRUFBRSxJQUFJLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUU7UUFDN0QsSUFBSSxFQUFFLEtBQUssYUFBYSxFQUFFO1lBQ3hCLFNBQVM7U0FDVjtRQUNELEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7S0FDM0I7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FDakMsTUFBbUMsRUFDbkMsZUFBNkM7SUFFN0MsOEVBQThFO0lBQzlFLE1BQU0sS0FBSyxHQUFHLHlCQUF5QixDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLElBQVcsRUFBRSxFQUFFO1FBQ2pGLHlFQUF5RTtRQUN6RSxNQUFNLFFBQVEsR0FBbUIsSUFBSSxDQUFDLE1BQU0sQ0FDMUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFDMUUsRUFBb0IsQ0FDckIsQ0FBQztRQUNGLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3RCxPQUFPLGVBQWUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDekQsQ0FBQyxDQUFDLENBQUM7SUFDSCxJQUFJLEtBQUssWUFBWSxZQUFZLEVBQUU7UUFDakMscUVBQXFFO1FBQ3JFLGVBQWUsQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRTtZQUMvQyxJQUFJLEVBQUUsS0FBSyxNQUFNLEVBQUU7Z0JBQ2pCLE1BQU0sQ0FBQyxTQUFTLEVBQUUsR0FBRyxRQUFRLENBQUMsR0FBRyxJQUFJLENBQUM7Z0JBQ3RDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEdBQUcsUUFBUSxDQUFDLENBQUM7YUFDcEM7UUFDSCxDQUFDLENBQUMsQ0FBQztLQUNKO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/messages.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/messages.d.ts new file mode 100644 index 000000000000..c8e36c087a49 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/messages.d.ts @@ -0,0 +1,45 @@ +/** + * Represents a transport bus request. + */ +export interface RequestMessage { + /** + * The message ID. + */ + msgId: number; + /** + * The data. + */ + payload: Payload; +} +/** + * Represents a transport bus response. + */ +export interface ResponseMessage { + /** + * The message ID. + */ + msgId: number; + /** + * The data. + */ + payload?: Payload; + /** + * The error, if any. + */ + error?: string; +} +/** + * A message stemming from an event. + */ +export interface EventMessage { + /** + * The event data. + */ + payload: Payload; +} +/** + * Is this an event message? + * @returns If the msgId was blank. + */ +export declare function isEventMessage(msg: ResponseMessage | EventMessage): msg is EventMessage; +//# sourceMappingURL=messages.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/messages.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/messages.d.ts.map new file mode 100644 index 000000000000..115e820679b1 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/messages.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/transport/dispatch/messages.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,OAAO;IACrC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,OAAO;IACtC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,OAAO;IACnC;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EACpC,GAAG,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,GACpD,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,CAE9B"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/messages.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/messages.js new file mode 100644 index 000000000000..b5d765952379 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/dispatch/messages.js @@ -0,0 +1,8 @@ +/** + * Is this an event message? + * @returns If the msgId was blank. + */ +export function isEventMessage(msg) { + return msg.msgId === undefined; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVzc2FnZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHJhbnNwb3J0L2Rpc3BhdGNoL21lc3NhZ2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQTBDQTs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUM1QixHQUFxRDtJQUVyRCxPQUFRLEdBQWdDLENBQUMsS0FBSyxLQUFLLFNBQVMsQ0FBQztBQUMvRCxDQUFDIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/index.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/index.d.ts new file mode 100644 index 000000000000..0989a811a399 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/index.d.ts @@ -0,0 +1,12 @@ +export * from './dispatch/create_dispatch_fn.js'; +export * from './dispatch/create_dispatch_proxy.js'; +export * from './dispatch/messages.js'; +export * from './interface/connector.js'; +export * from './interface/listener.js'; +export * from './interface/socket.js'; +export * from './interface/transferable.js'; +export * from './transport_client.js'; +export * from './transport_server.js'; +export * from './browser/index.js'; +export * from './node/index.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/index.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/index.d.ts.map new file mode 100644 index 000000000000..d5bded64e1d1 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAC;AACjD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/index.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/index.js new file mode 100644 index 000000000000..70b1b56c44c3 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/index.js @@ -0,0 +1,12 @@ +export * from './dispatch/create_dispatch_fn.js'; +export * from './dispatch/create_dispatch_proxy.js'; +export * from './dispatch/messages.js'; +export * from './interface/connector.js'; +export * from './interface/listener.js'; +export * from './interface/socket.js'; +export * from './interface/transferable.js'; +export * from './transport_client.js'; +export * from './transport_server.js'; +export * from './browser/index.js'; +export * from './node/index.js'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhbnNwb3J0L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsa0NBQWtDLENBQUM7QUFDakQsY0FBYyxxQ0FBcUMsQ0FBQztBQUNwRCxjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyxpQkFBaUIsQ0FBQyJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/connector.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/connector.d.ts new file mode 100644 index 000000000000..828e9aab7b29 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/connector.d.ts @@ -0,0 +1,8 @@ +import { Socket } from './socket.js'; +/** + * Opens a socket with corresponding TransportListener. + */ +export interface Connector { + createSocket(): Promise; +} +//# sourceMappingURL=connector.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/connector.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/connector.d.ts.map new file mode 100644 index 000000000000..62006c17cebc --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/connector.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../../../src/transport/interface/connector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACjC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/connector.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/connector.js new file mode 100644 index 000000000000..7d5ac106da90 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/connector.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC9pbnRlcmZhY2UvY29ubmVjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/listener.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/listener.d.ts new file mode 100644 index 000000000000..4d0baa435727 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/listener.d.ts @@ -0,0 +1,13 @@ +/// +import EventEmitter from 'events'; +import { Socket } from './socket.js'; +/** + * Once opened, an implementation of a TransportListener will emit `new_socket` events as new clients connect. + * Possible implementations could include MessageChannels or WebSockets. + */ +export interface Listener extends EventEmitter { + open(): void; + close(): void; + on(name: 'new_socket', cb: (client: Socket) => void): this; +} +//# sourceMappingURL=listener.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/listener.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/listener.d.ts.map new file mode 100644 index 000000000000..a326bd6b210b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/listener.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../../src/transport/interface/listener.ts"],"names":[],"mappings":";AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;GAGG;AACH,MAAM,WAAW,QAAS,SAAQ,YAAY;IAC5C,IAAI,IAAI,IAAI,CAAC;IAEb,KAAK,IAAI,IAAI,CAAC;IAEd,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;CAC5D"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/listener.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/listener.js new file mode 100644 index 000000000000..196998386cb0 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/listener.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdGVuZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHJhbnNwb3J0L2ludGVyZmFjZS9saXN0ZW5lci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/socket.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/socket.d.ts new file mode 100644 index 000000000000..39e6a4e4a6a4 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/socket.d.ts @@ -0,0 +1,13 @@ +/** + * Represents one end of a socket connection. + * A message sent via `send` will be handled by the corresponding Socket's handler function at the other end. + * Implementations could use e.g. MessagePorts for communication between browser workers, + * or WebSockets for communication between processes. + * If `registerHandler` callback receives `undefined` that signals the other end closed. + */ +export interface Socket { + send(msg: any, transfer?: Transferable[]): Promise; + registerHandler(cb: (msg: any) => any): void; + close(): void; +} +//# sourceMappingURL=socket.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/socket.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/socket.d.ts.map new file mode 100644 index 000000000000..a7714e3a5392 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/socket.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../../src/transport/interface/socket.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,eAAe,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,GAAG,IAAI,CAAC;IAC7C,KAAK,IAAI,IAAI,CAAC;CACf"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/socket.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/socket.js new file mode 100644 index 000000000000..5a28a6f054d6 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/socket.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ja2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC9pbnRlcmZhY2Uvc29ja2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/transferable.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/transferable.d.ts new file mode 100644 index 000000000000..f8ef5f290e3d --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/transferable.d.ts @@ -0,0 +1,60 @@ +declare const $transferable: unique symbol; +/** + * A descriptor representing a payload with transferable components. + * These components will have ownership transfered when published on an event bus. + */ +export interface TransferDescriptor { + /** + * Marked as transferable. + */ + [$transferable]: true; + /** + * The payload with the transferable objects. + */ + send: T; + /** + * The objects to transfer. + */ + transferables: Transferable[]; +} +/** + * + */ +export declare function isTransferDescriptor(thing: any): thing is TransferDescriptor; +/** + * Mark a transferable object as such, so it will no be serialized and + * deserialized on messaging with the main thread, but to transfer + * ownership of it to the receiving thread. + * + * Only works with array buffers, message ports and few more special + * types of objects, but it's much faster than serializing and + * deserializing them. + * + * Note: + * The transferable object cannot be accessed by this thread again + * unless the receiving thread transfers it back again! + * + * @param transferable - Array buffer, message port or similar. + * @see https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast + */ +export declare function Transfer(transferable: Transferable): TransferDescriptor; +/** + * Mark transferable objects within an arbitrary object or array as + * being a transferable object. They will then not be serialized + * and deserialized on messaging with the main thread, but ownership + * of them will be tranferred to the receiving thread. + * + * Only array buffers, message ports and few more special types of + * objects can be transferred, but it's much faster than serializing and + * deserializing them. + * + * Note: + * The transferable object cannot be accessed by this thread again + * unless the receiving thread transfers it back again! + * + * @param transferable - Array buffer, message port or similar. + * @see https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast + */ +export declare function Transfer(payload: T, transferables: Transferable[]): TransferDescriptor; +export {}; +//# sourceMappingURL=transferable.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/transferable.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/transferable.d.ts.map new file mode 100644 index 000000000000..5126c83a736e --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/transferable.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transferable.d.ts","sourceRoot":"","sources":["../../../src/transport/interface/transferable.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,aAAa,eAAgC,CAAC;AAEpD;;;GAGG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,GAAG;IACzC;;OAEG;IACH,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC;IACtB;;OAEG;IACH,IAAI,EAAE,CAAC,CAAC;IACR;;OAEG;IACH,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAWD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,kBAAkB,CAE5E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,YAAY,EAAE,YAAY,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/transferable.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/transferable.js new file mode 100644 index 000000000000..e815bbc8331b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/interface/transferable.js @@ -0,0 +1,35 @@ +const $transferable = Symbol('thread.transferable'); +/** + * + */ +function isTransferable(thing) { + if (!thing || typeof thing !== 'object') + return false; + // Don't check too thoroughly, since the list of transferable things in JS might grow over time + return true; +} +/** + * + */ +export function isTransferDescriptor(thing) { + return thing && typeof thing === 'object' && thing[$transferable]; +} +/** + * Create a transfer descriptor, marking these as transferable. + * @param payload - The payload. + * @param transferables - The transferable objects. + * @returns The descriptor. + */ +export function Transfer(payload, transferables) { + if (!transferables) { + if (!isTransferable(payload)) + throw Error(); + transferables = [payload]; + } + return { + [$transferable]: true, + send: payload, + transferables, + }; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXJhYmxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC9pbnRlcmZhY2UvdHJhbnNmZXJhYmxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0FBcUJwRDs7R0FFRztBQUNILFNBQVMsY0FBYyxDQUFDLEtBQVU7SUFDaEMsSUFBSSxDQUFDLEtBQUssSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDdEQsK0ZBQStGO0lBQy9GLE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLEtBQVU7SUFDN0MsT0FBTyxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztBQUNwRSxDQUFDO0FBdUNEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBSSxPQUFVLEVBQUUsYUFBOEI7SUFDcEUsSUFBSSxDQUFDLGFBQWEsRUFBRTtRQUNsQixJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQztZQUFFLE1BQU0sS0FBSyxFQUFFLENBQUM7UUFDNUMsYUFBYSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7S0FDM0I7SUFFRCxPQUFPO1FBQ0wsQ0FBQyxhQUFhLENBQUMsRUFBRSxJQUFJO1FBQ3JCLElBQUksRUFBRSxPQUFPO1FBQ2IsYUFBYTtLQUNkLENBQUM7QUFDSixDQUFDIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/index.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/index.d.ts new file mode 100644 index 000000000000..a39c08a0d40f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/index.d.ts @@ -0,0 +1,3 @@ +export * from './node_connector.js'; +export * from './node_listener.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/index.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/index.d.ts.map new file mode 100644 index 000000000000..1ea4d29d0e86 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transport/node/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/index.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/index.js new file mode 100644 index 000000000000..07a86060aae7 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/index.js @@ -0,0 +1,3 @@ +export * from './node_connector.js'; +export * from './node_listener.js'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHJhbnNwb3J0L25vZGUvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLG9CQUFvQixDQUFDIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector.d.ts new file mode 100644 index 000000000000..b1d8890543c5 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector.d.ts @@ -0,0 +1,17 @@ +/// +import { Worker } from 'worker_threads'; +import { Connector } from '../interface/connector.js'; +import { NodeConnectorSocket } from './node_connector_socket.js'; +/** + * Creates sockets backed by a Node worker. + */ +export declare class NodeConnector implements Connector { + private worker; + constructor(worker: Worker); + /** + * Creates a socket backed by a node worker. + * @returns The socket. + */ + createSocket(): Promise; +} +//# sourceMappingURL=node_connector.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector.d.ts.map new file mode 100644 index 000000000000..57ef4337f761 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"node_connector.d.ts","sourceRoot":"","sources":["../../../src/transport/node/node_connector.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE;;GAEG;AACH,qBAAa,aAAc,YAAW,SAAS;IACjC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAElC;;;OAGG;IACH,YAAY;CAGb"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector.js new file mode 100644 index 000000000000..2525dc380925 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector.js @@ -0,0 +1,17 @@ +import { NodeConnectorSocket } from './node_connector_socket.js'; +/** + * Creates sockets backed by a Node worker. + */ +export class NodeConnector { + constructor(worker) { + this.worker = worker; + } + /** + * Creates a socket backed by a node worker. + * @returns The socket. + */ + createSocket() { + return Promise.resolve(new NodeConnectorSocket(this.worker)); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV9jb25uZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHJhbnNwb3J0L25vZGUvbm9kZV9jb25uZWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFakU7O0dBRUc7QUFDSCxNQUFNLE9BQU8sYUFBYTtJQUN4QixZQUFvQixNQUFjO1FBQWQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtJQUFHLENBQUM7SUFFdEM7OztPQUdHO0lBQ0gsWUFBWTtRQUNWLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLG1CQUFtQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQy9ELENBQUM7Q0FDRiJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector_socket.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector_socket.d.ts new file mode 100644 index 000000000000..a87192030c26 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector_socket.d.ts @@ -0,0 +1,27 @@ +/// +import { Worker } from 'worker_threads'; +import { Socket } from '../interface/socket.js'; +/** + * A socket implementation using a Node worker. + */ +export declare class NodeConnectorSocket implements Socket { + private worker; + constructor(worker: Worker); + /** + * Send a message. + * @param msg - The message. + * @param transfer - Objects to transfer ownership of. + * @returns A void promise. + */ + send(msg: any, transfer?: Transferable[]): Promise; + /** + * Register a message handler. + * @param cb - The handler function. + */ + registerHandler(cb: (msg: any) => any): void; + /** + * Remove all listeners from our worker. + */ + close(): void; +} +//# sourceMappingURL=node_connector_socket.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector_socket.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector_socket.d.ts.map new file mode 100644 index 000000000000..a7bbda3ff576 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector_socket.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"node_connector_socket.d.ts","sourceRoot":"","sources":["../../../src/transport/node/node_connector_socket.ts"],"names":[],"mappings":";AAAA,OAAO,EAAoB,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD;;GAEG;AACH,qBAAa,mBAAoB,YAAW,MAAM;IACpC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAElC;;;;;OAKG;IACH,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,GAAE,YAAY,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;;OAGG;IACH,eAAe,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,GAAG,IAAI;IAI5C;;OAEG;IACH,KAAK;CAIN"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector_socket.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector_socket.js new file mode 100644 index 000000000000..25eb2f34e286 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_connector_socket.js @@ -0,0 +1,33 @@ +/** + * A socket implementation using a Node worker. + */ +export class NodeConnectorSocket { + constructor(worker) { + this.worker = worker; + } + /** + * Send a message. + * @param msg - The message. + * @param transfer - Objects to transfer ownership of. + * @returns A void promise. + */ + send(msg, transfer = []) { + this.worker.postMessage(msg, transfer); + return Promise.resolve(); + } + /** + * Register a message handler. + * @param cb - The handler function. + */ + registerHandler(cb) { + this.worker.on('message', cb); + } + /** + * Remove all listeners from our worker. + */ + close() { + void this.send(undefined); + this.worker.removeAllListeners(); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV9jb25uZWN0b3Jfc29ja2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyYW5zcG9ydC9ub2RlL25vZGVfY29ubmVjdG9yX3NvY2tldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQTs7R0FFRztBQUNILE1BQU0sT0FBTyxtQkFBbUI7SUFDOUIsWUFBb0IsTUFBYztRQUFkLFdBQU0sR0FBTixNQUFNLENBQVE7SUFBRyxDQUFDO0lBRXRDOzs7OztPQUtHO0lBQ0gsSUFBSSxDQUFDLEdBQVEsRUFBRSxXQUEyQixFQUFFO1FBQzFDLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxRQUE4QixDQUFDLENBQUM7UUFDN0QsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVEOzs7T0FHRztJQUNILGVBQWUsQ0FBQyxFQUFxQjtRQUNuQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSztRQUNILEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsTUFBTSxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDbkMsQ0FBQztDQUNGIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener.d.ts new file mode 100644 index 000000000000..e9bf26a20ce1 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener.d.ts @@ -0,0 +1,18 @@ +/// +import EventEmitter from 'events'; +import { Listener } from '../interface/listener.js'; +/** + * A socket listener that works with Node. + */ +export declare class NodeListener extends EventEmitter implements Listener { + constructor(); + /** + * Open the listener. + */ + open(): void; + /** + * Close the listener. + */ + close(): void; +} +//# sourceMappingURL=node_listener.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener.d.ts.map new file mode 100644 index 000000000000..e15acee10b1c --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"node_listener.d.ts","sourceRoot":"","sources":["../../../src/transport/node/node_listener.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD;;GAEG;AACH,qBAAa,YAAa,SAAQ,YAAa,YAAW,QAAQ;;IAKhE;;OAEG;IACH,IAAI;IAIJ;;OAEG;IACH,KAAK;CACN"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener.js new file mode 100644 index 000000000000..318369699af1 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener.js @@ -0,0 +1,22 @@ +import { parentPort } from 'worker_threads'; +import EventEmitter from 'events'; +import { NodeListenerSocket } from './node_listener_socket.js'; +/** + * A socket listener that works with Node. + */ +export class NodeListener extends EventEmitter { + constructor() { + super(); + } + /** + * Open the listener. + */ + open() { + this.emit('new_socket', new NodeListenerSocket(parentPort)); + } + /** + * Close the listener. + */ + close() { } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV9saXN0ZW5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90cmFuc3BvcnQvbm9kZS9ub2RlX2xpc3RlbmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM1QyxPQUFPLFlBQVksTUFBTSxRQUFRLENBQUM7QUFFbEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFL0Q7O0dBRUc7QUFDSCxNQUFNLE9BQU8sWUFBYSxTQUFRLFlBQVk7SUFDNUM7UUFDRSxLQUFLLEVBQUUsQ0FBQztJQUNWLENBQUM7SUFFRDs7T0FFRztJQUNILElBQUk7UUFDRixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLGtCQUFrQixDQUFDLFVBQWlCLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssS0FBSSxDQUFDO0NBQ1gifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener_socket.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener_socket.d.ts new file mode 100644 index 000000000000..ee114126debb --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener_socket.d.ts @@ -0,0 +1,27 @@ +/// +import { MessagePort } from 'worker_threads'; +import { Socket } from '../interface/socket.js'; +/** + * An implementation of a TransportSocket using MessagePorts. + */ +export declare class NodeListenerSocket implements Socket { + private port; + constructor(port: MessagePort); + /** + * Send a message over this port. + * @param msg - The message. + * @param transfer - Transferable objects. + * @returns A void promise. + */ + send(msg: any, transfer?: Transferable[]): Promise; + /** + * Add a handler to this port. + * @param cb - The handler function. + */ + registerHandler(cb: (msg: any) => any): void; + /** + * Close this socket. + */ + close(): void; +} +//# sourceMappingURL=node_listener_socket.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener_socket.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener_socket.d.ts.map new file mode 100644 index 000000000000..31986e0cd027 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener_socket.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"node_listener_socket.d.ts","sourceRoot":"","sources":["../../../src/transport/node/node_listener_socket.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAoB,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD;;GAEG;AACH,qBAAa,kBAAmB,YAAW,MAAM;IACnC,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,WAAW;IAErC;;;;;OAKG;IACH,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,GAAE,YAAY,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;;OAGG;IACH,eAAe,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,GAAG,IAAI;IAI5C;;OAEG;IACH,KAAK;CAKN"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener_socket.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener_socket.js new file mode 100644 index 000000000000..483c51bc0ffb --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/node/node_listener_socket.js @@ -0,0 +1,34 @@ +/** + * An implementation of a TransportSocket using MessagePorts. + */ +export class NodeListenerSocket { + constructor(port) { + this.port = port; + } + /** + * Send a message over this port. + * @param msg - The message. + * @param transfer - Transferable objects. + * @returns A void promise. + */ + send(msg, transfer = []) { + this.port.postMessage(msg, transfer); + return Promise.resolve(); + } + /** + * Add a handler to this port. + * @param cb - The handler function. + */ + registerHandler(cb) { + this.port.on('message', cb); + } + /** + * Close this socket. + */ + close() { + void this.send(undefined); + this.port.removeAllListeners(); + this.port.close(); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV9saXN0ZW5lcl9zb2NrZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHJhbnNwb3J0L25vZGUvbm9kZV9saXN0ZW5lcl9zb2NrZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0E7O0dBRUc7QUFDSCxNQUFNLE9BQU8sa0JBQWtCO0lBQzdCLFlBQW9CLElBQWlCO1FBQWpCLFNBQUksR0FBSixJQUFJLENBQWE7SUFBRyxDQUFDO0lBRXpDOzs7OztPQUtHO0lBQ0gsSUFBSSxDQUFDLEdBQVEsRUFBRSxXQUEyQixFQUFFO1FBQzFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxRQUE4QixDQUFDLENBQUM7UUFDM0QsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVEOzs7T0FHRztJQUNILGVBQWUsQ0FBQyxFQUFxQjtRQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDOUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSztRQUNILEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNwQixDQUFDO0NBQ0YifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_client.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_client.d.ts new file mode 100644 index 000000000000..a70ae9fea5e1 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_client.d.ts @@ -0,0 +1,44 @@ +/// +import EventEmitter from 'events'; +import { Connector } from './interface/connector.js'; +/** + * Augments the TransportClient class with more precise EventEmitter types. + */ +export interface TransportClient extends EventEmitter { + on(name: 'event_msg', handler: (payload: Payload) => void): this; + emit(name: 'event_msg', payload: Payload): boolean; +} +/** + * A TransportClient provides a request/response and event api to a corresponding TransportServer. + * If `broadcast` is called on TransportServer, TransportClients will emit an `event_msg`. + * The `request` method will block until a response is returned from the TransportServer's dispatch function. + * Request multiplexing is supported. + */ +export declare class TransportClient extends EventEmitter { + private transportConnect; + private msgId; + private pendingRequests; + private socket?; + constructor(transportConnect: Connector); + /** + * Create and register our socket using our Connector. + */ + open(): Promise; + /** + * Close this and stop listening for messages. + */ + close(): void; + /** + * Queue a request. + * @param payload - The request payload. + * @param transfer - Objects to transfer ownership of. + * @returns A promise of the query result. + */ + request(payload: Payload, transfer?: Transferable[]): Promise; + /** + * Handle an incoming socket message. + * @param msg - The message. + */ + private handleSocketMessage; +} +//# sourceMappingURL=transport_client.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_client.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_client.d.ts.map new file mode 100644 index 000000000000..9d6db62d26d3 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_client.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transport_client.d.ts","sourceRoot":"","sources":["../../src/transport/transport_client.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAiBrD;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,OAAO,CAAE,SAAQ,YAAY;IAC5D,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IACjE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;CACpD;AAED;;;;;GAKG;AACH,qBAAa,eAAe,CAAC,OAAO,CAAE,SAAQ,YAAY;IAK5C,OAAO,CAAC,gBAAgB;IAJpC,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,eAAe,CAAwB;IAC/C,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEJ,gBAAgB,EAAE,SAAS;IAI/C;;OAEG;IACG,IAAI;IAKV;;OAEG;IACH,KAAK;IAML;;;;;OAKG;IACH,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,YAAY,EAAE;IAanD;;;OAGG;IACH,OAAO,CAAC,mBAAmB;CAsB5B"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_client.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_client.js new file mode 100644 index 000000000000..fa875f151090 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_client.js @@ -0,0 +1,80 @@ +import { createDebugLogger } from "@aztec/foundation"; +import EventEmitter from "events"; +import { isEventMessage } from "./dispatch/messages.js"; +const debug = createDebugLogger("aztec:transport_client"); +/** + * A TransportClient provides a request/response and event api to a corresponding TransportServer. + * If `broadcast` is called on TransportServer, TransportClients will emit an `event_msg`. + * The `request` method will block until a response is returned from the TransportServer's dispatch function. + * Request multiplexing is supported. + */ +export class TransportClient extends EventEmitter { + constructor(transportConnect) { + super(); + this.transportConnect = transportConnect; + this.msgId = 0; + this.pendingRequests = []; + } + /** + * Create and register our socket using our Connector. + */ + async open() { + this.socket = await this.transportConnect.createSocket(); + this.socket.registerHandler((msg) => this.handleSocketMessage(msg)); + } + /** + * Close this and stop listening for messages. + */ + close() { + this.socket?.close(); + this.socket = undefined; + this.removeAllListeners(); + } + /** + * Queue a request. + * @param payload - The request payload. + * @param transfer - Objects to transfer ownership of. + * @returns A promise of the query result. + */ + request(payload, transfer) { + if (!this.socket) { + throw new Error("Socket not open."); + } + const msgId = this.msgId++; + const msg = { msgId, payload }; + debug(`->`, msg); + return new Promise((resolve, reject) => { + this.pendingRequests.push({ resolve, reject, msgId }); + this.socket.send(msg, transfer).catch(reject); + }); + } + /** + * Handle an incoming socket message. + * @param msg - The message. + */ + handleSocketMessage(msg) { + if (msg === undefined) { + // The remote socket closed. + this.close(); + return; + } + debug(`<-`, msg); + if (isEventMessage(msg)) { + this.emit("event_msg", msg.payload); + return; + } + const reqIndex = this.pendingRequests.findIndex( + (r) => r.msgId === msg.msgId + ); + if (reqIndex === -1) { + return; + } + const [pending] = this.pendingRequests.splice(reqIndex, 1); + if (msg.error) { + pending.reject(new Error(msg.error)); + } else { + pending.resolve(msg.payload); + } + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNwb3J0X2NsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90cmFuc3BvcnQvdHJhbnNwb3J0X2NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDL0MsT0FBTyxZQUFZLE1BQU0sUUFBUSxDQUFDO0FBQ2xDLE9BQU8sRUFBZ0IsY0FBYyxFQUFtQixNQUFNLHdCQUF3QixDQUFDO0FBSXZGLE1BQU0sS0FBSyxHQUFHLGlCQUFpQixDQUFDLHdCQUF3QixDQUFDLENBQUM7QUFzQjFEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLGVBQXlCLFNBQVEsWUFBWTtJQUt4RCxZQUFvQixnQkFBMkI7UUFDN0MsS0FBSyxFQUFFLENBQUM7UUFEVSxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQVc7UUFKdkMsVUFBSyxHQUFHLENBQUMsQ0FBQztRQUNWLG9CQUFlLEdBQXFCLEVBQUUsQ0FBQztJQUsvQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsSUFBSTtRQUNSLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDekQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUNyQixJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztRQUN4QixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxPQUFPLENBQUMsT0FBZ0IsRUFBRSxRQUF5QjtRQUNqRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUM7U0FDckM7UUFDRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDM0IsTUFBTSxHQUFHLEdBQUcsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDL0IsS0FBSyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNqQixPQUFPLElBQUksT0FBTyxDQUFNLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzFDLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQ3RELElBQUksQ0FBQyxNQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDakQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQUMsR0FBaUU7UUFDM0YsSUFBSSxHQUFHLEtBQUssU0FBUyxFQUFFO1lBQ3JCLDRCQUE0QjtZQUM1QixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDYixPQUFPO1NBQ1I7UUFDRCxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2pCLElBQUksY0FBYyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNwQyxPQUFPO1NBQ1I7UUFDRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVFLElBQUksUUFBUSxLQUFLLENBQUMsQ0FBQyxFQUFFO1lBQ25CLE9BQU87U0FDUjtRQUNELE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDM0QsSUFBSSxHQUFHLENBQUMsS0FBSyxFQUFFO1lBQ2IsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztTQUN0QzthQUFNO1lBQ0wsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDOUI7SUFDSCxDQUFDO0NBQ0YifQ== diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_server.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_server.d.ts new file mode 100644 index 000000000000..109e9210f8b9 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_server.d.ts @@ -0,0 +1,44 @@ +import { Listener } from './interface/listener.js'; +/** + * Keeps track of clients, providing a broadcast, and request/response api with multiplexing. + */ +export declare class TransportServer { + private listener; + private msgHandlerFn; + private sockets; + constructor(listener: Listener, msgHandlerFn: (msg: Payload) => Promise); + /** + * Start accepting new connections. + */ + start(): void; + /** + * Stops accepting new connections. It doesn't close existing sockets. + * It's expected the clients will gracefully complete by closing their end, sending an `undefined` message. + */ + stop(): void; + /** + * Broadcast a message. + * @param msg - The message. + */ + broadcast(msg: Payload): Promise; + /** + * New socket registration. + * @param socket - The socket to register. + */ + private handleNewSocket; + /** + * Detect the 'transferables' argument to our socket from our message + * handler return type. + * @param data - The return object. + * @returns - The data and the. + */ + private getPayloadAndTransfers; + /** + * Handles a socket message from a listener. + * @param socket - The socket. + * @param requestMessage - The message to handle. + * @returns The socket response. + */ + private handleSocketMessage; +} +//# sourceMappingURL=transport_server.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_server.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_server.d.ts.map new file mode 100644 index 000000000000..103804f98084 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_server.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transport_server.d.ts","sourceRoot":"","sources":["../../src/transport/transport_server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAInD;;GAEG;AACH,qBAAa,eAAe,CAAC,OAAO;IAGtB,OAAO,CAAC,QAAQ;IAAY,OAAO,CAAC,YAAY;IAF5D,OAAO,CAAC,OAAO,CAAgB;gBAEX,QAAQ,EAAE,QAAQ,EAAU,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,CAAC;IAE5F;;OAEG;IACH,KAAK;IAKL;;;OAGG;IACH,IAAI;IAIJ;;;OAGG;IACG,SAAS,CAAC,GAAG,EAAE,OAAO;IAI5B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAcvB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;;;;OAKG;YACW,mBAAmB;CAalC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_server.js b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_server.js new file mode 100644 index 000000000000..b1865345fc41 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/transport/transport_server.js @@ -0,0 +1,89 @@ +import { isTransferDescriptor } from './interface/transferable.js'; +/** + * Keeps track of clients, providing a broadcast, and request/response api with multiplexing. + */ +export class TransportServer { + constructor(listener, msgHandlerFn) { + this.listener = listener; + this.msgHandlerFn = msgHandlerFn; + this.sockets = []; + } + /** + * Start accepting new connections. + */ + start() { + this.listener.on('new_socket', client => this.handleNewSocket(client)); + this.listener.open(); + } + /** + * Stops accepting new connections. It doesn't close existing sockets. + * It's expected the clients will gracefully complete by closing their end, sending an `undefined` message. + */ + stop() { + this.listener.close(); + } + /** + * Broadcast a message. + * @param msg - The message. + */ + async broadcast(msg) { + await Promise.all(this.sockets.map(s => s.send({ payload: msg }))); + } + /** + * New socket registration. + * @param socket - The socket to register. + */ + handleNewSocket(socket) { + socket.registerHandler(async (msg) => { + if (msg === undefined) { + // Client socket has closed. Remove it from the list of sockets. Call close on it for any cleanup. + const socketIndex = this.sockets.findIndex(s => s === socket); + const [closingSocket] = this.sockets.splice(socketIndex, 1); + closingSocket.close(); + return; + } + return await this.handleSocketMessage(socket, msg); + }); + this.sockets.push(socket); + } + /** + * Detect the 'transferables' argument to our socket from our message + * handler return type. + * @param data - The return object. + * @returns - The data and the. + */ + getPayloadAndTransfers(data) { + if (isTransferDescriptor(data)) { + // We treat PayloadWithTransfers specially so that we're able to + // attach transferables while keeping a simple return-type based usage + return [data.send, data.transferables]; + } + if (data instanceof Uint8Array) { + // We may want to devise a better solution to this. We maybe given a view over a non cloneable/transferrable + // ArrayBuffer (such as a view over wasm memory). In this case we want to take a copy, and then transfer it. + const respPayload = data instanceof Uint8Array && ArrayBuffer.isView(data) ? new Uint8Array(data) : data; + const transferables = data instanceof Uint8Array ? [respPayload.buffer] : []; + return [respPayload, transferables]; + } + return [data, []]; + } + /** + * Handles a socket message from a listener. + * @param socket - The socket. + * @param requestMessage - The message to handle. + * @returns The socket response. + */ + async handleSocketMessage(socket, { msgId, payload }) { + try { + const data = await this.msgHandlerFn(payload); + const [respPayload, transferables] = this.getPayloadAndTransfers(data); + const rep = { msgId, payload: respPayload }; + await socket.send(rep, transferables); + } + catch (err) { + const rep = { msgId, error: err.stack }; + await socket.send(rep); + } + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNwb3J0X3NlcnZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90cmFuc3BvcnQvdHJhbnNwb3J0X3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVuRTs7R0FFRztBQUNILE1BQU0sT0FBTyxlQUFlO0lBRzFCLFlBQW9CLFFBQWtCLEVBQVUsWUFBNEM7UUFBeEUsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUFVLGlCQUFZLEdBQVosWUFBWSxDQUFnQztRQUZwRixZQUFPLEdBQWEsRUFBRSxDQUFDO0lBRWdFLENBQUM7SUFFaEc7O09BRUc7SUFDSCxLQUFLO1FBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQUk7UUFDRixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsU0FBUyxDQUFDLEdBQVk7UUFDMUIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssZUFBZSxDQUFDLE1BQWM7UUFDcEMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUMsR0FBRyxFQUFDLEVBQUU7WUFDakMsSUFBSSxHQUFHLEtBQUssU0FBUyxFQUFFO2dCQUNyQixrR0FBa0c7Z0JBQ2xHLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxDQUFDO2dCQUM5RCxNQUFNLENBQUMsYUFBYSxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUM1RCxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ3RCLE9BQU87YUFDUjtZQUNELE9BQU8sTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3JELENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssc0JBQXNCLENBQUMsSUFBUztRQUN0QyxJQUFJLG9CQUFvQixDQUFDLElBQUksQ0FBQyxFQUFFO1lBQzlCLGdFQUFnRTtZQUNoRSxzRUFBc0U7WUFDdEUsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1NBQ3hDO1FBQ0QsSUFBSSxJQUFJLFlBQVksVUFBVSxFQUFFO1lBQzlCLDRHQUE0RztZQUM1Ryw0R0FBNEc7WUFDNUcsTUFBTSxXQUFXLEdBQUcsSUFBSSxZQUFZLFVBQVUsSUFBSSxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ3pHLE1BQU0sYUFBYSxHQUFHLElBQUksWUFBWSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDN0UsT0FBTyxDQUFDLFdBQVcsRUFBRSxhQUFhLENBQUMsQ0FBQztTQUNyQztRQUNELE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEIsQ0FBQztJQUNEOzs7OztPQUtHO0lBQ0ssS0FBSyxDQUFDLG1CQUFtQixDQUFDLE1BQWMsRUFBRSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQTJCO1FBQzNGLElBQUk7WUFDRixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFOUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxhQUFhLENBQUMsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdkUsTUFBTSxHQUFHLEdBQTZCLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsQ0FBQztZQUV0RSxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1NBQ3ZDO1FBQUMsT0FBTyxHQUFRLEVBQUU7WUFDakIsTUFBTSxHQUFHLEdBQTZCLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbEUsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3hCO0lBQ0gsQ0FBQztDQUNGIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/async_call_state.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/wasm/async_call_state.d.ts new file mode 100644 index 000000000000..e466ea487603 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/async_call_state.d.ts @@ -0,0 +1,74 @@ +import { WasmModule } from "./wasm_module.js"; +/** + * The state of an asynchronous WASM function. + */ +export interface AsyncFnState { + /** + * Is this a contination? + */ + continuation: boolean; + /** + * A result, if one exists. + */ + result?: any; +} +/** + * To enable asynchronous callbacks from wasm to js, we leverage asyncify. + * Https://kripken.github.io/blog/wasm/2019/07/16/asyncify.html. + * + * This class holds state and logic specific to handling async calls from wasm to js. + * A single instance of this class is instantiated as part of BarretenbergWasm. + * It allocates some memory for the asyncify stack data and initialises it. + * + * To make an async call into the wasm, just call `call` the same as in BarretenbergWasm, only it returns a promise. + * + * To make an async import that will be called from the wasm, wrap a function with the signature: + * my_func(state: AsyncFnState, ...args) + * with a call to `wrapImportFn`. + * The arguments are whatever the original call arguments were. The addition of AsyncFnState as the first argument + * allows for the detection of wether the function is continuing after the the async call has completed. + * If `state.continuation` is false, the function should start its async operation and return the promise. + * If `state.continuation` is true, the function can get the result from `state.result` perform any finalisation, + * and return an (optional) value to the wasm. + */ +export declare class AsyncCallState { + private ASYNCIFY_DATA_SIZE; + private asyncifyDataAddr; + private asyncPromise?; + private wasm; + private state?; + private callExport; + /** + * Initialize the call hooks with a WasmModule. + * @param wasm - The module. + */ + init(wasm: WasmModule): void; + /** + * Log a message. + * @param args - The message arguments. + */ + private debug; + /** + * Free the data associated with async call states. + */ + destroy(): void; + /** + * We call the wasm function, that will in turn call back into js via callImport and set this.asyncPromise and + * enable the instrumented "record stack unwinding" code path. + * Once the stack has unwound out of the wasm call, we enter into a loop of resolving the promise set in the call + * to callImport, and calling back into the wasm to rewind the stack and continue execution. + * @param name - The function name. + * @param args - The function args. + * @returns The function result. + */ + call(name: string, ...args: any): Promise; + /** + * Wrap a WASM import function. + * @param fn - The function. + * @returns A wrapped version with asyncify calls. + */ + wrapImportFn( + fn: (state: AsyncFnState, ...args: any[]) => any + ): (...args: any[]) => any; +} +//# sourceMappingURL=async_call_state.d.ts.map diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/async_call_state.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/wasm/async_call_state.d.ts.map new file mode 100644 index 000000000000..ae4697ced4cf --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/async_call_state.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"async_call_state.d.ts","sourceRoot":"","sources":["../../src/wasm/async_call_state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,MAAM,CAAC,EAAE,GAAG,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,gBAAgB,CAAU;IAClC,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,KAAK,CAAC,CAAe;IAC7B,OAAO,CAAC,UAAU,CAA8B;IAEhD;;;OAGG;IACI,IAAI,CAAC,IAAI,EAAE,UAAU;IAY5B;;;OAGG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACI,OAAO;IAKd;;;;;;;;OAQG;IACU,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG;IA2B5C;;;;OAIG;IACI,YAAY,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,aACjD,GAAG,EAAE;CAkBzB"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/async_call_state.js b/yarn-project/.yalc/@aztec/wasm/dest/wasm/async_call_state.js new file mode 100644 index 000000000000..b24bb8432f6f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/async_call_state.js @@ -0,0 +1,111 @@ +/** + * To enable asynchronous callbacks from wasm to js, we leverage asyncify. + * Https://kripken.github.io/blog/wasm/2019/07/16/asyncify.html. + * + * This class holds state and logic specific to handling async calls from wasm to js. + * A single instance of this class is instantiated as part of BarretenbergWasm. + * It allocates some memory for the asyncify stack data and initialises it. + * + * To make an async call into the wasm, just call `call` the same as in BarretenbergWasm, only it returns a promise. + * + * To make an async import that will be called from the wasm, wrap a function with the signature: + * my_func(state: AsyncFnState, ...args) + * with a call to `wrapImportFn`. + * The arguments are whatever the original call arguments were. The addition of AsyncFnState as the first argument + * allows for the detection of wether the function is continuing after the the async call has completed. + * If `state.continuation` is false, the function should start its async operation and return the promise. + * If `state.continuation` is true, the function can get the result from `state.result` perform any finalisation, + * and return an (optional) value to the wasm. + */ +export class AsyncCallState { + constructor() { + this.ASYNCIFY_DATA_SIZE = 16 * 1024; + } + /** + * Initialize the call hooks with a WasmModule. + * @param wasm - The module. + */ + init(wasm) { + this.wasm = wasm; + this.callExport = (name, ...args) => wasm.call(name, ...args); + // Allocate memory for asyncify stack data. + this.asyncifyDataAddr = this.callExport('bbmalloc', this.ASYNCIFY_DATA_SIZE); + // TODO: is this view construction problematic like in WasmModule? + const view = new Uint32Array(wasm.getRawMemory().buffer); + // First two integers of asyncify data, are the start and end of the stack region. + view[this.asyncifyDataAddr >> 2] = this.asyncifyDataAddr + 8; + view[(this.asyncifyDataAddr + 4) >> 2] = this.asyncifyDataAddr + this.ASYNCIFY_DATA_SIZE; + } + /** + * Log a message. + * @param args - The message arguments. + */ + debug(...args) { + this.wasm.getLogger()(...args); + } + /** + * Free the data associated with async call states. + */ + destroy() { + // Free call stack data. + this.callExport('bbfree', this.asyncifyDataAddr); + } + /** + * We call the wasm function, that will in turn call back into js via callImport and set this.asyncPromise and + * enable the instrumented "record stack unwinding" code path. + * Once the stack has unwound out of the wasm call, we enter into a loop of resolving the promise set in the call + * to callImport, and calling back into the wasm to rewind the stack and continue execution. + * @param name - The function name. + * @param args - The function args. + * @returns The function result. + */ + async call(name, ...args) { + if (this.state) { + throw new Error(`Can only handle one async call at a time: ${name}(${args})`); + } + this.state = { continuation: false }; + let result = this.callExport(name, ...args); + while (this.asyncPromise) { + // Disable the instrumented "record stack unwinding" code path. + this.callExport('asyncify_stop_unwind'); + this.debug('stack unwound.'); + // Wait for the async work to complete. + this.state.result = await this.asyncPromise; + this.state.continuation = true; + this.debug('result set starting rewind.'); + // Enable "stack rewinding" code path. + this.callExport('asyncify_start_rewind', this.asyncifyDataAddr); + // Call function again to rebuild the stack, and continue where we left off. + result = this.callExport(name, ...args); + } + // Cleanup + this.state = undefined; + return result; + } + /** + * Wrap a WASM import function. + * @param fn - The function. + * @returns A wrapped version with asyncify calls. + */ + wrapImportFn(fn) { + return (...args) => { + if (!this.asyncPromise) { + // We are in the normal code path. Start the async fetch of data. + this.asyncPromise = fn(this.state, ...args); + // Enable "record stack unwinding" code path and return. + this.callExport('asyncify_start_unwind', this.asyncifyDataAddr); + } + else { + // We are in the stack rewind code path, called once the promise is resolved. + // Save the result data back to the wasm, disable stack rewind code paths, and return. + this.callExport('asyncify_stop_rewind'); + const result = fn(this.state, ...args); + // Cleanup. + this.asyncPromise = undefined; + this.state = { continuation: false }; + return result; + } + }; + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmNfY2FsbF9zdGF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy93YXNtL2FzeW5jX2NhbGxfc3RhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBZ0JBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7QUFDSCxNQUFNLE9BQU8sY0FBYztJQUEzQjtRQUNVLHVCQUFrQixHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFtR3pDLENBQUM7SUE1RkM7OztPQUdHO0lBQ0ksSUFBSSxDQUFDLElBQWdCO1FBQzFCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxJQUFZLEVBQUUsR0FBRyxJQUFXLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDN0UsMkNBQTJDO1FBQzNDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUM3RSxrRUFBa0U7UUFDbEUsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3pELGtGQUFrRjtRQUNsRixJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxDQUFDLENBQUM7UUFDN0QsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDM0YsQ0FBQztJQUVEOzs7T0FHRztJQUNLLEtBQUssQ0FBQyxHQUFHLElBQVc7UUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7T0FFRztJQUNJLE9BQU87UUFDWix3QkFBd0I7UUFDeEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ksS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFZLEVBQUUsR0FBRyxJQUFTO1FBQzFDLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLElBQUksSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO1NBQy9FO1FBQ0QsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUNyQyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO1FBRTVDLE9BQU8sSUFBSSxDQUFDLFlBQVksRUFBRTtZQUN4QiwrREFBK0Q7WUFDL0QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1lBQ3hDLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUM3Qix1Q0FBdUM7WUFDdkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDO1lBQzVDLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztZQUMvQixJQUFJLENBQUMsS0FBSyxDQUFDLDZCQUE2QixDQUFDLENBQUM7WUFDMUMsc0NBQXNDO1lBQ3RDLElBQUksQ0FBQyxVQUFVLENBQUMsdUJBQXVCLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDaEUsNEVBQTRFO1lBQzVFLE1BQU0sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO1NBQ3pDO1FBRUQsVUFBVTtRQUNWLElBQUksQ0FBQyxLQUFLLEdBQUcsU0FBUyxDQUFDO1FBRXZCLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksWUFBWSxDQUFDLEVBQWdEO1FBQ2xFLE9BQU8sQ0FBQyxHQUFHLElBQVcsRUFBRSxFQUFFO1lBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFO2dCQUN0QixpRUFBaUU7Z0JBQ2pFLElBQUksQ0FBQyxZQUFZLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztnQkFDN0Msd0RBQXdEO2dCQUN4RCxJQUFJLENBQUMsVUFBVSxDQUFDLHVCQUF1QixFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO2FBQ2pFO2lCQUFNO2dCQUNMLDZFQUE2RTtnQkFDN0Usc0ZBQXNGO2dCQUN0RixJQUFJLENBQUMsVUFBVSxDQUFDLHNCQUFzQixDQUFDLENBQUM7Z0JBQ3hDLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7Z0JBQ3hDLFdBQVc7Z0JBQ1gsSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUM7Z0JBQzlCLElBQUksQ0FBQyxLQUFLLEdBQUcsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLENBQUM7Z0JBQ3JDLE9BQU8sTUFBTSxDQUFDO2FBQ2Y7UUFDSCxDQUFDLENBQUM7SUFDSixDQUFDO0NBQ0YifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/empty_wasi_sdk.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/wasm/empty_wasi_sdk.d.ts new file mode 100644 index 000000000000..8409a7022b6d --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/empty_wasi_sdk.d.ts @@ -0,0 +1,26 @@ +/** + * Dummy implementation of a necessary part of the wasi api: + * https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md + * We don't use these functions, but the environment expects them. + * TODO find a way to update off of wasi 12. + */ +export declare const getEmptyWasiSdk: ( + debug?: import("@aztec/foundation").DebugLogger +) => { + clock_time_get(): void; + environ_get(): void; + environ_sizes_get(): void; + fd_close(): void; + fd_read(): void; + fd_write(): void; + fd_seek(): void; + fd_fdstat_get(): void; + fd_fdstat_set_flags(): void; + fd_prestat_get(): number; + fd_prestat_dir_name(): number; + path_open(): void; + path_filestat_get(): void; + proc_exit(): number; + random_get(): number; +}; +//# sourceMappingURL=empty_wasi_sdk.d.ts.map diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/empty_wasi_sdk.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/wasm/empty_wasi_sdk.d.ts.map new file mode 100644 index 000000000000..961a206c39f2 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/empty_wasi_sdk.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"empty_wasi_sdk.d.ts","sourceRoot":"","sources":["../../src/wasm/empty_wasi_sdk.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAGH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;CAkD1B,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/empty_wasi_sdk.js b/yarn-project/.yalc/@aztec/wasm/dest/wasm/empty_wasi_sdk.js new file mode 100644 index 000000000000..27f7a6436d2c --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/empty_wasi_sdk.js @@ -0,0 +1,63 @@ +import { createDebugLogger } from "@aztec/foundation"; +/** + * Dummy implementation of a necessary part of the wasi api: + * https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md + * We don't use these functions, but the environment expects them. + * TODO find a way to update off of wasi 12. + */ +/* eslint-disable camelcase */ +/* eslint-disable jsdoc/require-jsdoc */ +export const getEmptyWasiSdk = ( + debug = createDebugLogger("wasm:empty_wasi_sdk") +) => ({ + clock_time_get() { + debug("clock_time_get"); + }, + environ_get() { + debug("environ_get"); + }, + environ_sizes_get() { + debug("environ_sizes_get"); + }, + fd_close() { + debug("fd_close"); + }, + fd_read() { + debug("fd_read"); + }, + fd_write() { + debug("fd_write"); + }, + fd_seek() { + debug("fd_seek"); + }, + fd_fdstat_get() { + debug("fd_fdstat_get"); + }, + fd_fdstat_set_flags() { + debug("fd_fdstat_set_flags"); + }, + fd_prestat_get() { + debug("fd_prestat_get"); + return 8; + }, + fd_prestat_dir_name() { + debug("fd_prestat_dir_name"); + return 28; + }, + path_open() { + debug("path_open"); + }, + path_filestat_get() { + debug("path_filestat_get"); + }, + proc_exit() { + debug("proc_exit"); + return 52; + }, + random_get() { + debug("random_get"); + return 1; + }, +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1wdHlfd2FzaV9zZGsuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd2FzbS9lbXB0eV93YXNpX3Nkay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFL0M7Ozs7O0dBS0c7QUFDSCw4QkFBOEI7QUFDOUIsd0NBQXdDO0FBQ3hDLE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxDQUFDLEtBQUssR0FBRyxpQkFBaUIsQ0FBQyxxQkFBcUIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3BGLGNBQWM7UUFDWixLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBQ0QsV0FBVztRQUNULEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUN2QixDQUFDO0lBQ0QsaUJBQWlCO1FBQ2YsS0FBSyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUNELFFBQVE7UUFDTixLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDcEIsQ0FBQztJQUNELE9BQU87UUFDTCxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUNELFFBQVE7UUFDTixLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDcEIsQ0FBQztJQUNELE9BQU87UUFDTCxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUNELGFBQWE7UUFDWCxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUNELG1CQUFtQjtRQUNqQixLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBQ0QsY0FBYztRQUNaLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3hCLE9BQU8sQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUNELG1CQUFtQjtRQUNqQixLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUM3QixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFDRCxTQUFTO1FBQ1AsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3JCLENBQUM7SUFDRCxpQkFBaUI7UUFDZixLQUFLLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBQ0QsU0FBUztRQUNQLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNuQixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFDRCxVQUFVO1FBQ1IsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3BCLE9BQU8sQ0FBQyxDQUFDO0lBQ1gsQ0FBQztDQUNGLENBQUMsQ0FBQyJ9 diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/index.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/wasm/index.d.ts new file mode 100644 index 000000000000..1247c354830b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/index.d.ts @@ -0,0 +1,3 @@ +export { AsyncCallState, AsyncFnState } from './async_call_state.js'; +export { WasmModule } from './wasm_module.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/index.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/wasm/index.d.ts.map new file mode 100644 index 000000000000..e4a88cedea07 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wasm/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/index.js b/yarn-project/.yalc/@aztec/wasm/dest/wasm/index.js new file mode 100644 index 000000000000..8c9ce830550e --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/index.js @@ -0,0 +1,3 @@ +export { AsyncCallState } from './async_call_state.js'; +export { WasmModule } from './wasm_module.js'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd2FzbS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQyJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/wasm_module.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/wasm/wasm_module.d.ts new file mode 100644 index 000000000000..f46e4ec65774 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/wasm_module.d.ts @@ -0,0 +1,110 @@ +/// +import { Buffer } from "buffer"; +/** + * WasmModule: + * Helper over a webassembly module. + * Assumes a few quirks. + * 1) the module expects wasi_snapshot_preview1 with the methods from getEmptyWasiSdk + * 2) of which the webassembly + * we instantiate only uses random_get (update this if more WASI sdk methods are needed). + */ +export declare class WasmModule { + private module; + private importFn; + private memory; + private heap; + private instance?; + private mutexQ; + private debug; + /** + * Create a wasm module. Should be followed by await init();. + * @param module - The module as a WebAssembly.Module or a Buffer. + * @param importFn - Imports expected by the WASM. + * @param loggerName - Optional, for debug logging. + */ + constructor( + module: WebAssembly.Module | Buffer, + importFn: (module: WasmModule) => any, + loggerName?: string + ); + /** + * Return the wasm source. + * @returns The source. + */ + getModule(): WebAssembly.Module | Buffer; + /** + * Initialize this wasm module. + * @param wasmImportEnv - Linked to a module called "env". Functions implementations referenced from e.g. C++. + * @param initial - 20 pages by default. 20*2**16 \> 1mb stack size plus other overheads. + * @param maximum - 8192 maximum by default. 512mb. + */ + init(initial?: number, maximum?: number): Promise; + /** + * The methods or objects exported by the WASM module. + * @returns An indexable object. + */ + exports(): any; + /** + * Get the current logger. + * @returns Logging function. + */ + getLogger(): any; + /** + * Add a logger. + * @param logger - Function to call when logging. + */ + addLogger(logger: any): void; + /** + * Calls into the WebAssembly. + * @param name - The method name. + * @param args - The arguments to the method. + * @returns The numeric method result. + */ + call(name: string, ...args: any): number; + /** + * Get the memory used by the WASM module. + * @returns A WebAssembly memory object. + */ + getRawMemory(): WebAssembly.Memory; + /** + * Get the memory used by the WASM module, as a byte array. + * @returns A Uint8Array view of the WASM module memory. + */ + getMemory(): Uint8Array; + /** + * The memory size in bytes. + * @returns Number of bytes. + */ + memSize(): number; + /** + * Get a slice of memory between two addresses. + * @param start - The start address. + * @param end - The end address. + * @returns A Uint8Array view of memory. + */ + getMemorySlice(start: number, end: number): Uint8Array; + /** + * Write data into the heap. + * @param offset - The address to write data at. + * @param arr - The data to write. + */ + writeMemory(offset: number, arr: Uint8Array): void; + /** + * Read WASM memory as a JS string. + * @param addr - The memory address. + * @returns A JS string. + */ + getMemoryAsString(addr: number): string; + /** + * When calling the wasm, sometimes a caller will require exclusive access over a series of calls. + * E.g. When a result is written to address 0, one cannot have another caller writing to the same address via + * writeMemory before the result is read via sliceMemory. + * Acquire() gets a single token from a fifo. The caller must call release() to add the token back. + */ + acquire(): Promise; + /** + * Release the mutex, letting another promise call acquire(). + */ + release(): void; +} +//# sourceMappingURL=wasm_module.d.ts.map diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/wasm_module.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/wasm/wasm_module.d.ts.map new file mode 100644 index 000000000000..2b5649b9d512 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/wasm_module.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"wasm_module.d.ts","sourceRoot":"","sources":["../../src/wasm/wasm_module.ts"],"names":[],"mappings":";AAAA,OAAO,EAAqB,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC;;;;;;;GAOG;AACH,qBAAa,UAAU;IAcnB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;IAdlB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,CAAuB;IACxC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,KAAK,CAAc;IAE3B;;;;;OAKG;gBAEO,MAAM,EAAE,WAAW,CAAC,MAAM,GAAG,MAAM,EACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,GAAG,EAC7C,UAAU,SAAS;IAMrB;;;OAGG;IACI,SAAS,IAAI,WAAW,CAAC,MAAM,GAAG,MAAM;IAG/C;;;;;OAKG;IACU,IAAI,CAAC,OAAO,SAAK,EAAE,OAAO,SAAO;IAwC9C;;;OAGG;IACI,OAAO,IAAI,GAAG;IAOrB;;;OAGG;IACI,SAAS;IAIhB;;;OAGG;IACI,SAAS,CAAC,MAAM,EAAE,WAAW;IAQpC;;;;;OAKG;IACI,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,MAAM;IAe/C;;;OAGG;IACI,YAAY,IAAI,WAAW,CAAC,MAAM;IAGzC;;;OAGG;IACI,SAAS,IAAI,UAAU;IAQ9B;;;OAGG;IACI,OAAO,IAAI,MAAM;IAIxB;;;;;OAKG;IACI,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;IAIhD;;;;OAIG;IACI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU;IAOlD;;;;OAIG;IACI,iBAAiB,CAAC,IAAI,EAAE,MAAM;IAQrC;;;;;OAKG;IACU,OAAO;IAIpB;;OAEG;IACI,OAAO;CAMf"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/wasm/wasm_module.js b/yarn-project/.yalc/@aztec/wasm/dest/wasm/wasm_module.js new file mode 100644 index 000000000000..852044bfd4d9 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/wasm/wasm_module.js @@ -0,0 +1,206 @@ +import { createDebugLogger } from "@aztec/foundation"; +import { Buffer } from "buffer"; +import { MemoryFifo } from "../memory_fifo.js"; +import { getEmptyWasiSdk } from "./empty_wasi_sdk.js"; +import { randomBytes } from "crypto"; +/** + * WasmModule: + * Helper over a webassembly module. + * Assumes a few quirks. + * 1) the module expects wasi_snapshot_preview1 with the methods from getEmptyWasiSdk + * 2) of which the webassembly + * we instantiate only uses random_get (update this if more WASI sdk methods are needed). + */ +export class WasmModule { + /** + * Create a wasm module. Should be followed by await init();. + * @param module - The module as a WebAssembly.Module or a Buffer. + * @param importFn - Imports expected by the WASM. + * @param loggerName - Optional, for debug logging. + */ + constructor(module, importFn, loggerName = "wasm") { + this.module = module; + this.importFn = importFn; + this.mutexQ = new MemoryFifo(); + this.debug = createDebugLogger(loggerName); + this.mutexQ.put(true); + } + /** + * Return the wasm source. + * @returns The source. + */ + getModule() { + return this.module; + } + /** + * Initialize this wasm module. + * @param wasmImportEnv - Linked to a module called "env". Functions implementations referenced from e.g. C++. + * @param initial - 20 pages by default. 20*2**16 \> 1mb stack size plus other overheads. + * @param maximum - 8192 maximum by default. 512mb. + */ + async init(initial = 20, maximum = 8192) { + this.debug( + `initial mem: ${initial} pages, ${ + (initial * 2 ** 16) / (1024 * 1024) + }mb. max mem: ${maximum} pages, ${(maximum * 2 ** 16) / (1024 * 1024)}mb` + ); + this.memory = new WebAssembly.Memory({ initial, maximum }); + // Create a view over the memory buffer. + // We do this once here, as webkit *seems* bugged out and actually shows this as new memory, + // thus displaying double. It's only worse if we create views on demand. I haven't established yet if + // the bug is also exasperating the termination on mobile due to "excessive memory usage". It could be + // that the OS is actually getting an incorrect reading in the same way the memory profiler does... + // The view will have to be recreated if the memory is grown. See getMemory(). + this.heap = new Uint8Array(this.memory.buffer); + // We support the wasi 12 SDK, but only implement random_get + /* eslint-disable camelcase */ + const importObj = { + wasi_snapshot_preview1: { + ...getEmptyWasiSdk(this.debug), + random_get: (arr, length) => { + arr = arr >>> 0; + const heap = this.getMemory(); + const randomData = randomBytes(length); + for (let i = arr; i < arr + length; ++i) { + heap[i] = randomData[i - arr]; + } + }, + }, + env: this.importFn(this), + }; + if (this.module instanceof WebAssembly.Module) { + this.instance = await WebAssembly.instantiate(this.module, importObj); + } else { + const { instance } = await WebAssembly.instantiate( + this.module, + importObj + ); + this.instance = instance; + } + } + /** + * The methods or objects exported by the WASM module. + * @returns An indexable object. + */ + exports() { + if (!this.instance) { + throw new Error("WasmModule: not initialized!"); + } + return this.instance.exports; + } + /** + * Get the current logger. + * @returns Logging function. + */ + getLogger() { + return this.debug; + } + /** + * Add a logger. + * @param logger - Function to call when logging. + */ + addLogger(logger) { + const oldDebug = this.debug; + this.debug = (...args) => { + logger(...args); + oldDebug(...args); + }; + } + /** + * Calls into the WebAssembly. + * @param name - The method name. + * @param args - The arguments to the method. + * @returns The numeric method result. + */ + call(name, ...args) { + if (!this.exports()[name]) { + throw new Error(`WASM function ${name} not found.`); + } + try { + // When returning values from the WASM, use >>> operator to convert + // signed representation to unsigned representation. + return this.exports()[name](...args) >>> 0; + } catch (err) { + const message = `WASM function ${name} aborted, error: ${err}`; + this.debug(message); + this.debug(err.stack); + throw new Error(message); + } + } + /** + * Get the memory used by the WASM module. + * @returns A WebAssembly memory object. + */ + getRawMemory() { + return this.memory; + } + /** + * Get the memory used by the WASM module, as a byte array. + * @returns A Uint8Array view of the WASM module memory. + */ + getMemory() { + // If the memory is grown, our view over it will be lost. Recreate the view. + if (this.heap.length === 0) { + this.heap = new Uint8Array(this.memory.buffer); + } + return this.heap; + } + /** + * The memory size in bytes. + * @returns Number of bytes. + */ + memSize() { + return this.getMemory().length; + } + /** + * Get a slice of memory between two addresses. + * @param start - The start address. + * @param end - The end address. + * @returns A Uint8Array view of memory. + */ + getMemorySlice(start, end) { + return this.getMemory().slice(start, end); + } + /** + * Write data into the heap. + * @param offset - The address to write data at. + * @param arr - The data to write. + */ + writeMemory(offset, arr) { + const mem = this.getMemory(); + for (let i = 0; i < arr.length; i++) { + mem[i + offset] = arr[i]; + } + } + /** + * Read WASM memory as a JS string. + * @param addr - The memory address. + * @returns A JS string. + */ + getMemoryAsString(addr) { + addr = addr >>> 0; + const m = this.getMemory(); + let i = addr; + for (; m[i] !== 0; ++i); + return Buffer.from(m.slice(addr, i)).toString("ascii"); + } + /** + * When calling the wasm, sometimes a caller will require exclusive access over a series of calls. + * E.g. When a result is written to address 0, one cannot have another caller writing to the same address via + * writeMemory before the result is read via sliceMemory. + * Acquire() gets a single token from a fifo. The caller must call release() to add the token back. + */ + async acquire() { + await this.mutexQ.get(); + } + /** + * Release the mutex, letting another promise call acquire(). + */ + release() { + if (this.mutexQ.length() !== 0) { + throw new Error("Release called but not acquired."); + } + this.mutexQ.put(true); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FzbV9tb2R1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd2FzbS93YXNtX21vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsaUJBQWlCLEVBQWUsTUFBTSxZQUFZLENBQUM7QUFDNUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUNoQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDL0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFckM7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBT3JCOzs7OztPQUtHO0lBQ0gsWUFDVSxNQUFtQyxFQUNuQyxRQUFxQyxFQUM3QyxVQUFVLEdBQUcsTUFBTTtRQUZYLFdBQU0sR0FBTixNQUFNLENBQTZCO1FBQ25DLGFBQVEsR0FBUixRQUFRLENBQTZCO1FBWHZDLFdBQU0sR0FBRyxJQUFJLFVBQVUsRUFBVyxDQUFDO1FBY3pDLElBQUksQ0FBQyxLQUFLLEdBQUcsaUJBQWlCLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFNBQVM7UUFDZCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDckIsQ0FBQztJQUNEOzs7OztPQUtHO0lBQ0ksS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxFQUFFLE9BQU8sR0FBRyxJQUFJO1FBQzVDLElBQUksQ0FBQyxLQUFLLENBQ1IsZ0JBQWdCLE9BQU8sV0FBVyxDQUFDLE9BQU8sR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixPQUFPLFdBQzFGLENBQUMsT0FBTyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxJQUFJLENBQ3BDLElBQUksQ0FDTCxDQUFDO1FBQ0YsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLFdBQVcsQ0FBQyxNQUFNLENBQUMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUMzRCx3Q0FBd0M7UUFDeEMsNEZBQTRGO1FBQzVGLHFHQUFxRztRQUNyRyxzR0FBc0c7UUFDdEcsbUdBQW1HO1FBQ25HLDhFQUE4RTtRQUM5RSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFL0MsNERBQTREO1FBQzVELDhCQUE4QjtRQUM5QixNQUFNLFNBQVMsR0FBRztZQUNoQixzQkFBc0IsRUFBRTtnQkFDdEIsR0FBRyxlQUFlLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztnQkFDOUIsVUFBVSxFQUFFLENBQUMsR0FBVyxFQUFFLE1BQWMsRUFBRSxFQUFFO29CQUMxQyxHQUFHLEdBQUcsR0FBRyxLQUFLLENBQUMsQ0FBQztvQkFDaEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO29CQUM5QixNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7b0JBQ3ZDLEtBQUssSUFBSSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxHQUFHLEdBQUcsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUFFO3dCQUN2QyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztxQkFDL0I7Z0JBQ0gsQ0FBQzthQUNGO1lBQ0QsR0FBRyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO1NBQ3pCLENBQUM7UUFFRixJQUFJLElBQUksQ0FBQyxNQUFNLFlBQVksV0FBVyxDQUFDLE1BQU0sRUFBRTtZQUM3QyxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1NBQ3ZFO2FBQU07WUFDTCxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxXQUFXLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDM0UsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7U0FDMUI7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksT0FBTztRQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2xCLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQztTQUNqRDtRQUNELE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7SUFDL0IsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFNBQVM7UUFDZCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDcEIsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFNBQVMsQ0FBQyxNQUFtQjtRQUNsQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQzVCLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxHQUFHLElBQVcsRUFBRSxFQUFFO1lBQzlCLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1lBQ2hCLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1FBQ3BCLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNJLElBQUksQ0FBQyxJQUFZLEVBQUUsR0FBRyxJQUFTO1FBQ3BDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDekIsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxhQUFhLENBQUMsQ0FBQztTQUNyRDtRQUNELElBQUk7WUFDRixtRUFBbUU7WUFDbkUsb0RBQW9EO1lBQ3BELE9BQU8sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQzVDO1FBQUMsT0FBTyxHQUFRLEVBQUU7WUFDakIsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLElBQUksb0JBQW9CLEdBQUcsRUFBRSxDQUFDO1lBQy9ELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDcEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUMxQjtJQUNILENBQUM7SUFDRDs7O09BR0c7SUFDSSxZQUFZO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBQ0Q7OztPQUdHO0lBQ0ksU0FBUztRQUNkLDRFQUE0RTtRQUM1RSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUMxQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDaEQ7UUFDRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDbkIsQ0FBQztJQUVEOzs7T0FHRztJQUNJLE9BQU87UUFDWixPQUFPLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxNQUFNLENBQUM7SUFDakMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksY0FBYyxDQUFDLEtBQWEsRUFBRSxHQUFXO1FBQzlDLE9BQU8sSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxXQUFXLENBQUMsTUFBYyxFQUFFLEdBQWU7UUFDaEQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQzdCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ25DLEdBQUcsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzFCO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxpQkFBaUIsQ0FBQyxJQUFZO1FBQ25DLElBQUksR0FBRyxJQUFJLEtBQUssQ0FBQyxDQUFDO1FBQ2xCLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDYixPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQUMsQ0FBQztRQUN4QixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksS0FBSyxDQUFDLE9BQU87UUFDbEIsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRDs7T0FFRztJQUNJLE9BQU87UUFDWixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxFQUFFO1lBQzlCLE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLENBQUMsQ0FBQztTQUNyRDtRQUNELElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hCLENBQUM7Q0FDRiJ9 diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/index.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/index.d.ts new file mode 100644 index 000000000000..5d25ae688b94 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/index.d.ts @@ -0,0 +1,3 @@ +export * from './web_worker.js'; +export * from './web_data_store.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/index.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/index.d.ts.map new file mode 100644 index 000000000000..c27488b261de --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/worker/browser/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/index.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/index.js new file mode 100644 index 000000000000..769c36e8a114 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/index.js @@ -0,0 +1,3 @@ +export * from './web_worker.js'; +export * from './web_data_store.js'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvd29ya2VyL2Jyb3dzZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLHFCQUFxQixDQUFDIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/start_web_module.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/start_web_module.d.ts new file mode 100644 index 000000000000..64305a49267f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/start_web_module.d.ts @@ -0,0 +1,7 @@ +import { WasmModule } from '../../wasm/wasm_module.js'; +/** + * Start the transport server corresponding to this module. + * @param module - The WasmModule to host. + */ +export declare function startWebModule(module: WasmModule): void; +//# sourceMappingURL=start_web_module.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/start_web_module.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/start_web_module.d.ts.map new file mode 100644 index 000000000000..236d51eb892a --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/start_web_module.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"start_web_module.d.ts","sourceRoot":"","sources":["../../../src/worker/browser/start_web_module.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,QAehD"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/start_web_module.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/start_web_module.js new file mode 100644 index 000000000000..107b51c35170 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/start_web_module.js @@ -0,0 +1,22 @@ +import { TransportServer, WorkerListener } from '../../transport/index.js'; +/** + * Start the transport server corresponding to this module. + * @param module - The WasmModule to host. + */ +export function startWebModule(module) { + const dispatch = async ({ fn, args }) => { + if (fn === '__destroyWorker__') { + transportServer.stop(); + return; + } + if (!module[fn]) { + throw new Error(`dispatch error, function not found: ${fn}`); + } + return await module[fn](...args); + }; + const transportListener = new WorkerListener(self); + const transportServer = new TransportServer(transportListener, dispatch); + module.addLogger((...args) => transportServer.broadcast({ fn: 'emit', args: ['log', ...args] })); + transportServer.start(); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnRfd2ViX21vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy93b3JrZXIvYnJvd3Nlci9zdGFydF93ZWJfbW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBZSxlQUFlLEVBQUUsY0FBYyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFHeEY7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxNQUFrQjtJQUMvQyxNQUFNLFFBQVEsR0FBRyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFlLEVBQUUsRUFBRTtRQUNuRCxJQUFJLEVBQUUsS0FBSyxtQkFBbUIsRUFBRTtZQUM5QixlQUFlLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDdkIsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFFLE1BQWMsQ0FBQyxFQUFFLENBQUMsRUFBRTtZQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1NBQzlEO1FBQ0QsT0FBTyxNQUFPLE1BQWMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQzVDLENBQUMsQ0FBQztJQUNGLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkQsTUFBTSxlQUFlLEdBQUcsSUFBSSxlQUFlLENBQWMsaUJBQWlCLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDdEYsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEdBQUcsSUFBVyxFQUFFLEVBQUUsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4RyxlQUFlLENBQUMsS0FBSyxFQUFFLENBQUM7QUFDMUIsQ0FBQyJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_data_store.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_data_store.d.ts new file mode 100644 index 000000000000..9b5ab4853d96 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_data_store.d.ts @@ -0,0 +1,23 @@ +/// +import { DataStore } from '../data_store.js'; +/** + * Cache for data used by wasm module. + * Stores in a LevelUp database. + */ +export declare class WebDataStore implements DataStore { + private db; + constructor(); + /** + * Lookup a key. + * @param key - Key to lookup. + * @returns The buffer. + */ + get(key: string): Promise; + /** + * Alter a key. + * @param key - Key to alter. + * @param value - Buffer to store. + */ + set(key: string, value: Buffer): Promise; +} +//# sourceMappingURL=web_data_store.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_data_store.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_data_store.d.ts.map new file mode 100644 index 000000000000..b786d902360b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_data_store.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"web_data_store.d.ts","sourceRoot":"","sources":["../../../src/worker/browser/web_data_store.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C;;;GAGG;AACH,qBAAa,YAAa,YAAW,SAAS;IAC5C,OAAO,CAAC,EAAE,CAAU;;IAUpB;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAInD;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGrD"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_data_store.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_data_store.js new file mode 100644 index 000000000000..49f7cd141720 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_data_store.js @@ -0,0 +1,32 @@ +import levelup from 'levelup'; +import memdown from 'memdown'; +/** + * Cache for data used by wasm module. + * Stores in a LevelUp database. + */ +export class WebDataStore { + constructor() { + // TODO: The whole point of this is to reduce memory load in the browser. + // Replace with leveljs so the data is stored in indexeddb and not in memory. + // Hack: Cast as any to work around package "broken" with node16 resolution + // See https://github.com/microsoft/TypeScript/issues/49160 + this.db = levelup(memdown()); + } + /** + * Lookup a key. + * @param key - Key to lookup. + * @returns The buffer. + */ + async get(key) { + return await this.db.get(key).catch(() => { }); + } + /** + * Alter a key. + * @param key - Key to alter. + * @param value - Buffer to store. + */ + async set(key, value) { + await this.db.put(key, value); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViX2RhdGFfc3RvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvd29ya2VyL2Jyb3dzZXIvd2ViX2RhdGFfc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxPQUFvQixNQUFNLFNBQVMsQ0FBQztBQUMzQyxPQUFPLE9BQU8sTUFBTSxTQUFTLENBQUM7QUFFOUI7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFlBQVk7SUFHdkI7UUFDRSx5RUFBeUU7UUFDekUsNkVBQTZFO1FBQzdFLDJFQUEyRTtRQUMzRSwyREFBMkQ7UUFDM0QsSUFBSSxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQUUsT0FBZSxFQUFFLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBVztRQUNuQixPQUFPLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFXLEVBQUUsS0FBYTtRQUNsQyxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNoQyxDQUFDO0NBQ0YifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_worker.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_worker.d.ts new file mode 100644 index 000000000000..45cdef0a2456 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_worker.d.ts @@ -0,0 +1,10 @@ +import { WasmWorker } from '../wasm_worker.js'; +/** + * Instantiate a web worker. + * @param url - The URL. + * @param initialMem - Initial memory pages. + * @param maxMem - Maximum memory pages. + * @returns The worker. + */ +export declare function createWebWorker(url: string, initialMem?: number, maxMem?: number): Promise; +//# sourceMappingURL=web_worker.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_worker.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_worker.d.ts.map new file mode 100644 index 000000000000..2756cc7c5dfb --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_worker.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"web_worker.d.ts","sourceRoot":"","sources":["../../../src/worker/browser/web_worker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAY5G"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_worker.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_worker.js new file mode 100644 index 000000000000..71a0e1b145f3 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/browser/web_worker.js @@ -0,0 +1,23 @@ +import { WasmModule } from '../../wasm/wasm_module.js'; +import { createDispatchProxy, TransportClient, WorkerConnector } from '../../transport/index.js'; +/** + * Instantiate a web worker. + * @param url - The URL. + * @param initialMem - Initial memory pages. + * @param maxMem - Maximum memory pages. + * @returns The worker. + */ +export async function createWebWorker(url, initialMem, maxMem) { + const worker = new Worker(url); + const transportConnect = new WorkerConnector(worker); + const transportClient = new TransportClient(transportConnect); + await transportClient.open(); + const remoteModule = createDispatchProxy(WasmModule, transportClient); + remoteModule.destroyWorker = async () => { + await transportClient.request({ fn: '__destroyWorker__', args: [] }); + transportClient.close(); + }; + await remoteModule.init(initialMem, maxMem); + return remoteModule; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViX3dvcmtlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy93b3JrZXIvYnJvd3Nlci93ZWJfd29ya2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsbUJBQW1CLEVBQWUsZUFBZSxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRzlHOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsZUFBZSxDQUFDLEdBQVcsRUFBRSxVQUFtQixFQUFFLE1BQWU7SUFDckYsTUFBTSxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDL0IsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNyRCxNQUFNLGVBQWUsR0FBRyxJQUFJLGVBQWUsQ0FBYyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQzNFLE1BQU0sZUFBZSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzdCLE1BQU0sWUFBWSxHQUFHLG1CQUFtQixDQUFDLFVBQVUsRUFBRSxlQUFlLENBQWUsQ0FBQztJQUNwRixZQUFZLENBQUMsYUFBYSxHQUFHLEtBQUssSUFBSSxFQUFFO1FBQ3RDLE1BQU0sZUFBZSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNyRSxlQUFlLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDMUIsQ0FBQyxDQUFDO0lBQ0YsTUFBTSxZQUFZLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM1QyxPQUFPLFlBQVksQ0FBQztBQUN0QixDQUFDIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/data_store.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/data_store.d.ts new file mode 100644 index 000000000000..0c9bd408c2d5 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/data_store.d.ts @@ -0,0 +1,9 @@ +/// +/** + * Simple read/write interface for wasm modules. + */ +export interface DataStore { + get(key: string): Promise; + set(key: string, value: Buffer): Promise; +} +//# sourceMappingURL=data_store.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/data_store.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/data_store.d.ts.map new file mode 100644 index 000000000000..4b0f53fd9d90 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/data_store.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"data_store.d.ts","sourceRoot":"","sources":["../../src/worker/data_store.ts"],"names":[],"mappings":";AAAA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC9C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/data_store.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/data_store.js new file mode 100644 index 000000000000..fd170823f17f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/data_store.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YV9zdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy93b3JrZXIvZGF0YV9zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/index.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/index.d.ts new file mode 100644 index 000000000000..07a37541295f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/index.d.ts @@ -0,0 +1,3 @@ +export { WorkerPool } from './worker_pool.js'; +export { WasmWorker } from './wasm_worker.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/index.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/index.d.ts.map new file mode 100644 index 000000000000..0960823e41d8 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/worker/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/index.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/index.js new file mode 100644 index 000000000000..c36435a7a312 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/index.js @@ -0,0 +1,2 @@ +export { WorkerPool } from './worker_pool.js'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd29ya2VyL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQyJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/index.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/index.d.ts new file mode 100644 index 000000000000..be9811545d57 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/index.d.ts @@ -0,0 +1,3 @@ +export * from './node_worker.js'; +export * from './node_data_store.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/index.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/index.d.ts.map new file mode 100644 index 000000000000..a406ecf876de --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/worker/node/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/index.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/index.js new file mode 100644 index 000000000000..cf7a08194501 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/index.js @@ -0,0 +1,3 @@ +export * from './node_worker.js'; +export * from './node_data_store.js'; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvd29ya2VyL25vZGUvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLHNCQUFzQixDQUFDIn0= \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_data_store.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_data_store.d.ts new file mode 100644 index 000000000000..5908d6599bb4 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_data_store.d.ts @@ -0,0 +1,22 @@ +/// +import { DataStore } from '../data_store.js'; +/** + * Cache for data used by wasm module. + */ +export declare class NodeDataStore implements DataStore { + private db; + constructor(path?: string); + /** + * Get a value from our DB. + * @param key - The key to look up. + * @returns The value. + */ + get(key: string): Promise; + /** + * Set a value in our DB. + * @param key - The key to update. + * @param value - The value to set. + */ + set(key: string, value: Buffer): Promise; +} +//# sourceMappingURL=node_data_store.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_data_store.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_data_store.d.ts.map new file mode 100644 index 000000000000..496c69d50944 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_data_store.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"node_data_store.d.ts","sourceRoot":"","sources":["../../../src/worker/node/node_data_store.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAK7C;;GAEG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC7C,OAAO,CAAC,EAAE,CAAU;gBAGR,IAAI,CAAC,EAAE,MAAM;IAMzB;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAInD;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGrD"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_data_store.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_data_store.js new file mode 100644 index 000000000000..57be391030af --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_data_store.js @@ -0,0 +1,31 @@ +import levelup from 'levelup'; +import leveldown from 'leveldown'; +import memdown from 'memdown'; +/** + * Cache for data used by wasm module. + */ +export class NodeDataStore { + // eslint-disable-next-line + constructor(path) { + // Hack: Cast as any to work around packages "broken" with node16 resolution + // See https://github.com/microsoft/TypeScript/issues/49160 + this.db = levelup(path ? leveldown(path) : memdown()); + } + /** + * Get a value from our DB. + * @param key - The key to look up. + * @returns The value. + */ + async get(key) { + return await this.db.get(key).catch(() => { }); + } + /** + * Set a value in our DB. + * @param key - The key to update. + * @param value - The value to set. + */ + async set(key, value) { + await this.db.put(key, value); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV9kYXRhX3N0b3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3dvcmtlci9ub2RlL25vZGVfZGF0YV9zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLE9BQW9CLE1BQU0sU0FBUyxDQUFDO0FBQzNDLE9BQU8sU0FBUyxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLE9BQU8sTUFBTSxTQUFTLENBQUM7QUFFOUI7O0dBRUc7QUFDSCxNQUFNLE9BQU8sYUFBYTtJQUd4QiwyQkFBMkI7SUFDM0IsWUFBWSxJQUFhO1FBQ3ZCLDRFQUE0RTtRQUM1RSwyREFBMkQ7UUFDM0QsSUFBSSxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBRSxTQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBRSxPQUFlLEVBQUUsQ0FBQyxDQUFDO0lBQzFFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFXO1FBQ25CLE9BQU8sTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQVcsRUFBRSxLQUFhO1FBQ2xDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLENBQUM7Q0FDRiJ9 \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_worker.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_worker.d.ts new file mode 100644 index 000000000000..5da7e01049d5 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_worker.d.ts @@ -0,0 +1,6 @@ +import { WasmWorker } from '../wasm_worker.js'; +/** + * + */ +export declare function createNodeWorker(filepath: string, initialMem?: number, maxMem?: number): Promise; +//# sourceMappingURL=node_worker.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_worker.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_worker.d.ts.map new file mode 100644 index 000000000000..26908ec619c6 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_worker.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"node_worker.d.ts","sourceRoot":"","sources":["../../../src/worker/node/node_worker.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAYlH"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_worker.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_worker.js new file mode 100644 index 000000000000..155e31ba16b5 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/node_worker.js @@ -0,0 +1,21 @@ +import { Worker } from 'worker_threads'; +import { createDispatchProxy, TransportClient } from '../../transport/index.js'; +import { NodeConnector } from '../../transport/index.js'; +import { WasmModule } from '../../wasm/wasm_module.js'; +/** + * + */ +export async function createNodeWorker(filepath, initialMem, maxMem) { + const worker = new Worker(filepath); + const transportConnect = new NodeConnector(worker); + const transportClient = new TransportClient(transportConnect); + await transportClient.open(); + const remoteModule = createDispatchProxy(WasmModule, transportClient); + remoteModule.destroyWorker = async () => { + await transportClient.request({ fn: '__destroyWorker__', args: [] }); + transportClient.close(); + }; + await remoteModule.init(initialMem, maxMem); + return remoteModule; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV93b3JrZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvd29ya2VyL25vZGUvbm9kZV93b3JrZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxtQkFBbUIsRUFBZSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDekQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBR3ZEOztHQUVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxRQUFnQixFQUFFLFVBQW1CLEVBQUUsTUFBZTtJQUMzRixNQUFNLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNwQyxNQUFNLGdCQUFnQixHQUFHLElBQUksYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ25ELE1BQU0sZUFBZSxHQUFHLElBQUksZUFBZSxDQUFjLGdCQUFnQixDQUFDLENBQUM7SUFDM0UsTUFBTSxlQUFlLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDN0IsTUFBTSxZQUFZLEdBQUcsbUJBQW1CLENBQUMsVUFBVSxFQUFFLGVBQWUsQ0FBZSxDQUFDO0lBQ3BGLFlBQVksQ0FBQyxhQUFhLEdBQUcsS0FBSyxJQUFJLEVBQUU7UUFDdEMsTUFBTSxlQUFlLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUFFLG1CQUFtQixFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3JFLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMxQixDQUFDLENBQUM7SUFDRixNQUFNLFlBQVksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzVDLE9BQU8sWUFBWSxDQUFDO0FBQ3RCLENBQUMifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/start_node_module.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/start_node_module.d.ts new file mode 100644 index 000000000000..c118c248f46f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/start_node_module.d.ts @@ -0,0 +1,7 @@ +import { WasmModule } from '../../wasm/wasm_module.js'; +/** + * Start the transport server corresponding to this module. + * @param module - The WasmModule to host. + */ +export declare function startNodeModule(module: WasmModule): void; +//# sourceMappingURL=start_node_module.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/start_node_module.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/start_node_module.d.ts.map new file mode 100644 index 000000000000..f006976f41e9 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/start_node_module.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"start_node_module.d.ts","sourceRoot":"","sources":["../../../src/worker/node/start_node_module.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAMvD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,QAejD"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/node/start_node_module.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/start_node_module.js new file mode 100644 index 000000000000..8d4aee385db4 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/node/start_node_module.js @@ -0,0 +1,26 @@ +import { parentPort } from 'worker_threads'; +import { NodeListener, TransportServer } from '../../transport/index.js'; +if (!parentPort) { + throw new Error('InvalidWorker'); +} +/** + * Start the transport server corresponding to this module. + * @param module - The WasmModule to host. + */ +export function startNodeModule(module) { + const dispatch = async ({ fn, args }) => { + if (fn === '__destroyWorker__') { + transportServer.stop(); + return; + } + if (!module[fn]) { + throw new Error(`dispatch error, function not found: ${fn}`); + } + return await module[fn](...args); + }; + const transportListener = new NodeListener(); + const transportServer = new TransportServer(transportListener, dispatch); + module.addLogger((...args) => transportServer.broadcast({ fn: 'emit', args: ['log', ...args] })); + transportServer.start(); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnRfbm9kZV9tb2R1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvd29ya2VyL25vZGUvc3RhcnRfbm9kZV9tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxZQUFZLEVBQWUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFHdEYsSUFBSSxDQUFDLFVBQVUsRUFBRTtJQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7Q0FDbEM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUFDLE1BQWtCO0lBQ2hELE1BQU0sUUFBUSxHQUFHLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQWUsRUFBRSxFQUFFO1FBQ25ELElBQUksRUFBRSxLQUFLLG1CQUFtQixFQUFFO1lBQzlCLGVBQWUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN2QixPQUFPO1NBQ1I7UUFDRCxJQUFJLENBQUUsTUFBYyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLEVBQUUsRUFBRSxDQUFDLENBQUM7U0FDOUQ7UUFDRCxPQUFPLE1BQU8sTUFBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDNUMsQ0FBQyxDQUFDO0lBQ0YsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO0lBQzdDLE1BQU0sZUFBZSxHQUFHLElBQUksZUFBZSxDQUFjLGlCQUFpQixFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3RGLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFHLElBQVcsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEcsZUFBZSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQzFCLENBQUMifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/wasm_worker.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/wasm_worker.d.ts new file mode 100644 index 000000000000..5796d84ec9e5 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/wasm_worker.d.ts @@ -0,0 +1,9 @@ +import { Proxify } from '../transport/index.js'; +import { WasmModule } from '../wasm/wasm_module.js'; +/** + * Represents either a WASM web worker, or node.js worker. + */ +export type WasmWorker = Proxify & { + destroyWorker(): void; +}; +//# sourceMappingURL=wasm_worker.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/wasm_worker.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/wasm_worker.d.ts.map new file mode 100644 index 000000000000..111acb92bbca --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/wasm_worker.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"wasm_worker.d.ts","sourceRoot":"","sources":["../../src/worker/wasm_worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG;IAAE,aAAa,IAAI,IAAI,CAAA;CAAE,CAAC"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/wasm_worker.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/wasm_worker.js new file mode 100644 index 000000000000..a886d8ce72e5 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/wasm_worker.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FzbV93b3JrZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd29ya2VyL3dhc21fd29ya2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ== \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/worker_pool.d.ts b/yarn-project/.yalc/@aztec/wasm/dest/worker/worker_pool.d.ts new file mode 100644 index 000000000000..62f2d879877d --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/worker_pool.d.ts @@ -0,0 +1,40 @@ +import { WasmWorker } from './wasm_worker.js'; +/** + * Type of a worker factory. + * Used to customize WorkerPool worker construction. + */ +export type CreateWorker = (name: string, minMem: number, maxMem: number) => WasmWorker; +/** + * Allocates a pool of WasmWorker's. + * Worker 0 is allocated MAX_PAGES memory pages. This is because worker 0 will need to hold the proving key + * (i.e. Has state), whereas the others are pure compute (they hold a little crs state). + */ +export declare class WorkerPool { + /** + * The maximum number of memory pages to be used by the webassembly. + */ + static MAX_PAGES: number; + /** + * The workers in the pool. + */ + private workers; + /** + * Create an instance and initialize the workers. + * @param createWorker - Worker factory. + * @param poolSize - Pool size. + * @returns An initialized WorkerPool. + */ + static new(createWorker: CreateWorker, poolSize: number): Promise; + /** + * Initialize the workers. + * @param createWorker - Worker factory(). + * @param poolSize - Pool size. + * @param maxMem - Max memory pages. + */ + init(createWorker: CreateWorker, poolSize: number, maxMem?: number): Promise; + /** + * Tell all workers in the pool to stop processing. + */ + destroy(): Promise; +} +//# sourceMappingURL=worker_pool.d.ts.map \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/worker_pool.d.ts.map b/yarn-project/.yalc/@aztec/wasm/dest/worker/worker_pool.d.ts.map new file mode 100644 index 000000000000..118733d8c5c7 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/worker_pool.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"worker_pool.d.ts","sourceRoot":"","sources":["../../src/worker/worker_pool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAI9C;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,UAAU,CAAC;AACxF;;;;GAIG;AACH,qBAAa,UAAU;IAYrB;;OAEG;IACH,OAAc,SAAS,SAAQ;IAC/B;;OAEG;IACH,OAAO,CAAC,OAAO,CAAoB;IAEnC;;;;;OAKG;WACU,GAAG,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM;IAM7D;;;;;OAKG;IACU,IAAI,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAuB;IAY7F;;OAEG;IACU,OAAO;CAGrB"} \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/dest/worker/worker_pool.js b/yarn-project/.yalc/@aztec/wasm/dest/worker/worker_pool.js new file mode 100644 index 000000000000..e98199d3de21 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/dest/worker/worker_pool.js @@ -0,0 +1,70 @@ +import { createDebugLogger } from "@aztec/foundation"; +const debug = createDebugLogger("bb:worker_pool"); +/** + * Allocates a pool of WasmWorker's. + * Worker 0 is allocated MAX_PAGES memory pages. This is because worker 0 will need to hold the proving key + * (i.e. Has state), whereas the others are pure compute (they hold a little crs state). + */ +export class WorkerPool { + constructor() { + /** + * The workers in the pool. + */ + this.workers = []; + } + /** + * Create an instance and initialize the workers. + * @param createWorker - Worker factory. + * @param poolSize - Pool size. + * @returns An initialized WorkerPool. + */ + static async new(createWorker, poolSize) { + const pool = new WorkerPool(); + await pool.init(createWorker, poolSize); + return pool; + } + /** + * Initialize the workers. + * @param createWorker - Worker factory(). + * @param poolSize - Pool size. + * @param maxMem - Max memory pages. + */ + async init(createWorker, poolSize, maxMem = WorkerPool.MAX_PAGES) { + debug(`creating ${poolSize} workers...`); + const start = new Date().getTime(); + this.workers = await Promise.all( + Array(poolSize) + .fill(0) + .map((_, i) => + createWorker( + `${i}`, + i === 0 ? Math.min(WorkerPool.MAX_PAGES, maxMem) : 768, + maxMem + ) + ) + ); + debug(`created workers: ${new Date().getTime() - start}ms`); + } + /** + * Tell all workers in the pool to stop processing. + */ + async destroy() { + await Promise.all(this.workers.map((w) => w.destroyWorker())); + } +} +// TODO(AD): Revisit what this means in aztec 3 context +// -- +// Introduction of low mem prover work (polynomial cache) may actually increase mem usage when the backing store isn't +// enabled. We were seeing intermittent failings related to memory in production for some users when limiting to +// 6660 (416MB). It would be nice to understand why this is (the non determinism and/or the increased mem usage). +// For now, increasing mem usage to 512MB. This maybe preferable to backing out the low mem work, but +// ironically may break the chance of us using it in mobile. +// We *could* enable the low memory backing store, but this needs a little bit of work to actually +// read/write from indexeddb, performance testing, and actual further memory load testing. +// At this point it's hard to know what our memory savings would be relative to just fully reverting the LMP. +// public static MAX_PAGES = 6660; +/** + * The maximum number of memory pages to be used by the webassembly. + */ +WorkerPool.MAX_PAGES = 8192; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2VyX3Bvb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd29ya2VyL3dvcmtlcl9wb29sLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUcvQyxNQUFNLEtBQUssR0FBRyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBT2xEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQUF2QjtRQWdCRTs7V0FFRztRQUNLLFlBQU8sR0FBaUIsRUFBRSxDQUFDO0lBc0NyQyxDQUFDO0lBcENDOzs7OztPQUtHO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsWUFBMEIsRUFBRSxRQUFnQjtRQUMzRCxNQUFNLElBQUksR0FBRyxJQUFJLFVBQVUsRUFBRSxDQUFDO1FBQzlCLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDeEMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQTBCLEVBQUUsUUFBZ0IsRUFBRSxNQUFNLEdBQUcsVUFBVSxDQUFDLFNBQVM7UUFDM0YsS0FBSyxDQUFDLFlBQVksUUFBUSxhQUFhLENBQUMsQ0FBQztRQUN6QyxNQUFNLEtBQUssR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ25DLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUM5QixLQUFLLENBQUMsUUFBUSxDQUFDO2FBQ1osSUFBSSxDQUFDLENBQUMsQ0FBQzthQUNQLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQ3ZHLENBQUM7UUFFRixLQUFLLENBQUMsb0JBQW9CLElBQUksSUFBSSxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsS0FBSyxJQUFJLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsT0FBTztRQUNsQixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzlELENBQUM7O0FBdkRELHVEQUF1RDtBQUN2RCxLQUFLO0FBQ0wsc0hBQXNIO0FBQ3RILGdIQUFnSDtBQUNoSCxpSEFBaUg7QUFDakgscUdBQXFHO0FBQ3JHLDREQUE0RDtBQUM1RCxrR0FBa0c7QUFDbEcsMEZBQTBGO0FBQzFGLDZHQUE2RztBQUM3RyxrQ0FBa0M7QUFDbEM7O0dBRUc7QUFDVyxvQkFBUyxHQUFHLElBQUksQ0FBQyJ9 diff --git a/yarn-project/.yalc/@aztec/wasm/node_modules/@aztec/foundation b/yarn-project/.yalc/@aztec/wasm/node_modules/@aztec/foundation new file mode 120000 index 000000000000..2e2545964211 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/node_modules/@aztec/foundation @@ -0,0 +1 @@ +../../../foundation \ No newline at end of file diff --git a/yarn-project/.yalc/@aztec/wasm/package.json b/yarn-project/.yalc/@aztec/wasm/package.json new file mode 100644 index 000000000000..8a766b2290dc --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/package.json @@ -0,0 +1,42 @@ +{ + "name": "@aztec/wasm", + "version": "0.0.0", + "type": "module", + "exports": "./dest/index.js", + "typedoc": { + "entryPoint": "./src/index.ts", + "displayName": "wasm", + "tsconfig": "./tsconfig.dest.json" + }, + "scripts": { + "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build:dev": "tsc -b tsconfig.dest.json --watch", + "clean": "rm -rf ./dest .tsbuildinfo", + "fix-eslint": "run -T eslint --fix ./src", + "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 53 ./src", + "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" + }, + "jest": { + "preset": "ts-jest/presets/default-esm", + "globals": { + "ts-jest": { + "useESM": true + } + }, + "moduleNameMapper": { + "^(\\.{1,2}/.*)\\.js$": "$1" + }, + "testRegex": "./src/.*\\.test\\.ts$", + "rootDir": "./src" + }, + "dependencies": { + "@aztec/foundation": "workspace:^", + "@types/leveldown": "^4.0.3", + "detect-node": "^2.1.0", + "leveldown": "^6.1.1", + "levelup": "^5.1.1", + "memdown": "^6.1.1", + "tslib": "^2.4.0" + }, + "yalcSig": "49e137843b2fae07ab3c4df8d2229740" +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/index.ts b/yarn-project/.yalc/@aztec/wasm/src/index.ts new file mode 100644 index 000000000000..7b34a6e732f6 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/index.ts @@ -0,0 +1,7 @@ +export { WebDataStore } from './worker/browser/index.js'; +export { NodeDataStore } from './worker/node/index.js'; +export { WasmWorker, WorkerPool } from './worker/index.js'; +export { WasmModule } from './wasm/index.js'; +export { AsyncCallState, AsyncFnState } from './wasm/index.js'; +export { DispatchMsg, WorkerListener, TransportServer, NodeListener } from './transport/index.js'; +export { Transfer, isTransferDescriptor } from './transport/interface/transferable.js'; diff --git a/yarn-project/.yalc/@aztec/wasm/src/memory_fifo.ts b/yarn-project/.yalc/@aztec/wasm/src/memory_fifo.ts new file mode 100644 index 000000000000..03dc63d93ee1 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/memory_fifo.ts @@ -0,0 +1,104 @@ +// TODO should come from a dependency +/** + * A simple fifo queue. It can grow unbounded. It can have multiple producers and consumers. + * Putting an item onto the queue always succeeds, unless either end() or cancel() has been called in which case + * the item being pushed is simply discarded. + */ +export class MemoryFifo { + private waiting: ((item: T | null) => void)[] = []; + private items: T[] = []; + private flushing = false; + + /** + * Length of queue. + * @returns integer. + */ + public length() { + return this.items.length; + } + + /** + * Returns next item within the queue, or blocks until and item has been put into the queue. + * If given a timeout, the promise will reject if no item is received after `timeout` seconds. + * If the queue is flushing, `null` is returned. + * @param timeout - In seconds. + * @returns Promise of result. + */ + public get(timeout?: number): Promise { + if (this.items.length) { + return Promise.resolve(this.items.shift()!); + } + + if (this.items.length === 0 && this.flushing) { + return Promise.resolve(null); + } + + return new Promise((resolve, reject) => { + this.waiting.push(resolve); + + if (timeout) { + setTimeout(() => { + const index = this.waiting.findIndex(r => r === resolve); + if (index > -1) { + this.waiting.splice(index, 1); + const err = new Error('Timeout getting item from queue.'); + reject(err); + } + }, timeout * 1000); + } + }); + } + + /** + * Put an item onto back of the queue. + * @param item - The item to enqueue. + */ + public put(item: T) { + if (this.flushing) { + return; + } else if (this.waiting.length) { + this.waiting.shift()!(item); + } else { + this.items.push(item); + } + } + + /** + * Once ended, no further items are added to queue. Consumers will consume remaining items within the queue. + * The queue is not reusable after calling `end()`. + * Any consumers waiting for an item receive null. + */ + public end() { + this.flushing = true; + this.waiting.forEach(resolve => resolve(null)); + } + + /** + * Once cancelled, all items are discarded from the queue, and no further items are added to the queue. + * The queue is not reusable after calling `cancel()`. + * Any consumers waiting for an item receive null. + */ + public cancel() { + this.flushing = true; + this.items = []; + this.waiting.forEach(resolve => resolve(null)); + } + + /** + * Helper method that can be used to continously consume and process items on the queue. + * @param handler - The item handler function. + */ + public async process(handler: (item: T) => Promise) { + try { + while (true) { + const item = await this.get(); + if (item === null) { + break; + } + await handler(item); + } + } catch (err) { + console.error('Queue handler exception:', err); + } + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/test/gcd.wasm b/yarn-project/.yalc/@aztec/wasm/src/test/gcd.wasm new file mode 100644 index 000000000000..19a859c306c3 Binary files /dev/null and b/yarn-project/.yalc/@aztec/wasm/src/test/gcd.wasm differ diff --git a/yarn-project/.yalc/@aztec/wasm/src/test/gcd.wat b/yarn-project/.yalc/@aztec/wasm/src/test/gcd.wat new file mode 100644 index 000000000000..ca209088e4d1 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/test/gcd.wat @@ -0,0 +1,27 @@ +(module + (func $gcd (param i32 i32) (result i32) + (local i32) + block ;; label = @1 + block ;; label = @2 + local.get 0 + br_if 0 (;@2;) + local.get 1 + local.set 2 + br 1 (;@1;) + end + loop ;; label = @2 + local.get 1 + local.get 0 + local.tee 2 + i32.rem_u + local.set 0 + local.get 2 + local.set 1 + local.get 0 + br_if 0 (;@2;) + end + end + local.get 2 + ) + (export "gcd" (func $gcd)) +) diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/browser/index.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/index.ts new file mode 100644 index 000000000000..24094f4965fa --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/index.ts @@ -0,0 +1,4 @@ +export * from './worker_connector.js'; +export * from './worker_listener.js'; +export * from './shared_worker_connector.js'; +export * from './shared_worker_listener.js'; diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/browser/message_port_socket.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/message_port_socket.ts new file mode 100644 index 000000000000..f82a3e0865ff --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/message_port_socket.ts @@ -0,0 +1,39 @@ +import { Socket } from '../interface/socket.js'; + +/** + * An implementation of a TransportSocket using MessagePorts. + */ +export class MessagePortSocket implements Socket { + /** + * Create a MessagePortSocket. + * @param port - MessagePort object to wrap. + */ + constructor(private port: MessagePort) {} + + /** + * Send a message over our message port. + * @param msg - The message. + * @param transfer - Objects to transfer ownership of. + */ + send(msg: any, transfer: Transferable[] = []): Promise { + this.port.postMessage(msg, transfer); + return Promise.resolve(); + } + + /** + * Add a message handler. + * @param cb - The handler. + */ + registerHandler(cb: (msg: any) => any): void { + this.port.onmessage = event => cb(event.data); + } + + /** + * Close this message port. + */ + close() { + void this.send(undefined); + this.port.onmessage = null; + this.port.close(); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/browser/shared_worker_connector.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/shared_worker_connector.ts new file mode 100644 index 000000000000..d6167961760d --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/shared_worker_connector.ts @@ -0,0 +1,21 @@ +import { Connector } from '../interface/connector.js'; +import { MessagePortSocket } from './message_port_socket.js'; + +/** + * Connector implementation which wraps a SharedWorker. + */ +export class SharedWorkerConnector implements Connector { + /** + * Create a SharedWorkerConnector. + * @param worker - A shared worker. + */ + constructor(private worker: SharedWorker) {} + + /** + * Create a Socket implementation with our mesage port. + * @returns The socket. + */ + createSocket() { + return Promise.resolve(new MessagePortSocket(this.worker.port)); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/browser/shared_worker_listener.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/shared_worker_listener.ts new file mode 100644 index 000000000000..cafd280e6e68 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/shared_worker_listener.ts @@ -0,0 +1,52 @@ +import EventEmitter from 'events'; +import { Listener } from '../interface/listener.js'; +import { MessagePortSocket } from './message_port_socket.js'; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/API/SharedWorkerGlobalScope. + */ +declare interface SharedWorkerGlobalScope { + /** + * Fired on shared workers when a new client connects. + */ + onconnect: any; +} + +/** + * Listens for connections to a shared worker. + */ +export class SharedWorkerListener extends EventEmitter implements Listener { + /** + * + * @param worker + */ + constructor(private worker: SharedWorkerGlobalScope) { + super(); + } + + /** + * + */ + open() { + this.worker.onconnect = this.handleMessageEvent; + } + + /** + * + */ + close() { + this.worker.onconnect = () => {}; + } + + /** + * + * @param event + */ + private handleMessageEvent = (event: MessageEvent) => { + const [port] = event.ports; + if (!port) { + return; + } + this.emit('new_socket', new MessagePortSocket(port)); + }; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/browser/worker_connector.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/worker_connector.ts new file mode 100644 index 000000000000..fbfc7efd22e2 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/worker_connector.ts @@ -0,0 +1,22 @@ +import { Connector } from '../interface/connector.js'; +import { MessagePortSocket } from './message_port_socket.js'; + +/** + * + */ +export class WorkerConnector implements Connector { + /** + * + * @param worker + */ + constructor(private worker: Worker) {} + + /** + * + */ + createSocket() { + const channel = new MessageChannel(); + this.worker.postMessage('', [channel.port2]); + return Promise.resolve(new MessagePortSocket(channel.port1)); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/browser/worker_listener.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/worker_listener.ts new file mode 100644 index 000000000000..201b3a685730 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/browser/worker_listener.ts @@ -0,0 +1,52 @@ +import EventEmitter from 'events'; +import { Listener } from '../interface/listener.js'; +import { MessagePortSocket } from './message_port_socket.js'; + +/** + * + */ +declare interface DedicatedWorkerGlobalScope { + /** + * + */ + onmessage: any; +} + +/** + * + */ +export class WorkerListener extends EventEmitter implements Listener { + /** + * + * @param worker + */ + constructor(private worker: DedicatedWorkerGlobalScope) { + super(); + } + + /** + * + */ + open() { + this.worker.onmessage = this.handleMessageEvent; + } + + /** + * + */ + close() { + this.worker.onmessage = () => {}; + } + + /** + * + * @param event + */ + private handleMessageEvent = (event: MessageEvent) => { + const [port] = event.ports; + if (!port) { + return; + } + this.emit('new_socket', new MessagePortSocket(port)); + }; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/dispatch/create_dispatch_fn.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/dispatch/create_dispatch_fn.ts new file mode 100644 index 000000000000..6e23e25a25f0 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/dispatch/create_dispatch_fn.ts @@ -0,0 +1,24 @@ +/** + * + */ +export interface DispatchMsg { + /** + * + */ + fn: string; + /** + * + */ + args: any[]; +} + +/** + * + */ +export function createDispatchFn(targetFn: () => any, debug = console.error) { + return async ({ fn, args }: DispatchMsg) => { + const target = targetFn(); + debug(`dispatching to ${target}: ${fn}`, args); + return await target[fn](...args); + }; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/dispatch/create_dispatch_proxy.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/dispatch/create_dispatch_proxy.ts new file mode 100644 index 000000000000..e9538448d3d4 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/dispatch/create_dispatch_proxy.ts @@ -0,0 +1,88 @@ +import { DispatchMsg } from './create_dispatch_fn.js'; +import { TransportClient } from '../transport_client.js'; +import { EventEmitter } from 'events'; +import { isTransferDescriptor, TransferDescriptor } from '../interface/transferable.js'; + +type FilterOutAttributes = { + [Key in keyof Base]: Base[Key] extends (...args: any) => any ? Base[Key] : never; +}; + +type PromisifyFunction any> = (...args: Parameters) => Promise>; + +type Promisify any }> = { + [Key in keyof Base]: ReturnType extends Promise ? Base[Key] : PromisifyFunction; +}; + +/** + * Unpack transfer types + */ +type TransferTypes = { + [Index in keyof Tuple]: Tuple[Index] | (Tuple[Index] extends Transferable ? TransferDescriptor : never); +}; + +/** + * Annoying: https://github.com/microsoft/TypeScript/issues/29919 + * There's a bug that means we can't map over the tuple or function parameter types to make them transferrable, if + * we use the Parameters builtin, and then try to map. + * So instead we inline the Parameters builtin and apply the TransferTypes to the parameters within the inline. + * Once the above is fixed we could in theory just do: + * + * type MakeFunctionTransferrable any> = ( + * ...args: TransferTypes> + * ) => ReturnType;. + */ +type MakeFunctionTransferrable any> = ( + ...args: TFunction extends (...args: infer P) => any ? TransferTypes

: never +) => ReturnType; + +type Transferrable any }> = { + [Key in keyof Base]: MakeFunctionTransferrable; +}; + +export type Proxify = Promisify>>; + +export function createDispatchProxyFromFn( + class_: { new (...args: any[]): T }, + requestFn: (fn: string) => (...args: any[]) => Promise, +): Proxify { + const proxy: any = class_.prototype instanceof EventEmitter ? new EventEmitter() : {}; + for (const fn of Object.getOwnPropertyNames(class_.prototype)) { + if (fn === 'constructor') { + continue; + } + proxy[fn] = requestFn(fn); + } + return proxy; +} + +/** + * Create a proxy object of our class T that uses transportClient + * @param class_ - Our class T. + * @param transportClient - The transport infrastructure. + * @returns A proxy over T. + */ +export function createDispatchProxy( + class_: { new (...args: any[]): T }, + transportClient: TransportClient, +): Proxify { + // Create a proxy of class_ that passes along methods over our transportClient + const proxy = createDispatchProxyFromFn(class_, (fn: string) => (...args: any[]) => { + // Pass our proxied function name and arguments over our transport client + const transfer: Transferable[] = args.reduce( + (acc, a) => (isTransferDescriptor(a) ? [...acc, ...a.transferables] : acc), + [] as Transferable[], + ); + args = args.map(a => (isTransferDescriptor(a) ? a.send : a)); + return transportClient.request({ fn, args }, transfer); + }); + if (proxy instanceof EventEmitter) { + // Handle proxied 'emit' calls if our proxy object is an EventEmitter + transportClient.on('event_msg', ({ fn, args }) => { + if (fn === 'emit') { + const [eventName, ...restArgs] = args; + proxy.emit(eventName, ...restArgs); + } + }); + } + return proxy; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/dispatch/messages.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/dispatch/messages.ts new file mode 100644 index 000000000000..49704dbde84b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/dispatch/messages.ts @@ -0,0 +1,51 @@ +/** + * Represents a transport bus request. + */ +export interface RequestMessage { + /** + * The message ID. + */ + msgId: number; + /** + * The data. + */ + payload: Payload; +} + +/** + * Represents a transport bus response. + */ +export interface ResponseMessage { + /** + * The message ID. + */ + msgId: number; + /** + * The data. + */ + payload?: Payload; + /** + * The error, if any. + */ + error?: string; +} + +/** + * A message stemming from an event. + */ +export interface EventMessage { + /** + * The event data. + */ + payload: Payload; +} + +/** + * Is this an event message? + * @returns If the msgId was blank. + */ +export function isEventMessage( + msg: ResponseMessage | EventMessage, +): msg is EventMessage { + return (msg as ResponseMessage).msgId === undefined; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/index.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/index.ts new file mode 100644 index 000000000000..1ea1f8c30cf3 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/index.ts @@ -0,0 +1,11 @@ +export * from './dispatch/create_dispatch_fn.js'; +export * from './dispatch/create_dispatch_proxy.js'; +export * from './dispatch/messages.js'; +export * from './interface/connector.js'; +export * from './interface/listener.js'; +export * from './interface/socket.js'; +export * from './interface/transferable.js'; +export * from './transport_client.js'; +export * from './transport_server.js'; +export * from './browser/index.js'; +export * from './node/index.js'; diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/interface/connector.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/interface/connector.ts new file mode 100644 index 000000000000..9d72f6574f72 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/interface/connector.ts @@ -0,0 +1,8 @@ +import { Socket } from './socket.js'; + +/** + * Opens a socket with corresponding TransportListener. + */ +export interface Connector { + createSocket(): Promise; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/interface/listener.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/interface/listener.ts new file mode 100644 index 000000000000..b6e533570a7b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/interface/listener.ts @@ -0,0 +1,14 @@ +import EventEmitter from 'events'; +import { Socket } from './socket.js'; + +/** + * Once opened, an implementation of a TransportListener will emit `new_socket` events as new clients connect. + * Possible implementations could include MessageChannels or WebSockets. + */ +export interface Listener extends EventEmitter { + open(): void; + + close(): void; + + on(name: 'new_socket', cb: (client: Socket) => void): this; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/interface/socket.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/interface/socket.ts new file mode 100644 index 000000000000..6da7ca436ed9 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/interface/socket.ts @@ -0,0 +1,12 @@ +/** + * Represents one end of a socket connection. + * A message sent via `send` will be handled by the corresponding Socket's handler function at the other end. + * Implementations could use e.g. MessagePorts for communication between browser workers, + * or WebSockets for communication between processes. + * If `registerHandler` callback receives `undefined` that signals the other end closed. + */ +export interface Socket { + send(msg: any, transfer?: Transferable[]): Promise; + registerHandler(cb: (msg: any) => any): void; + close(): void; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/interface/transferable.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/interface/transferable.ts new file mode 100644 index 000000000000..3ce8c59b320f --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/interface/transferable.ts @@ -0,0 +1,92 @@ +const $transferable = Symbol('thread.transferable'); + +/** + * A descriptor representing a payload with transferable components. + * These components will have ownership transfered when published on an event bus. + */ +export interface TransferDescriptor { + /** + * Marked as transferable. + */ + [$transferable]: true; + /** + * The payload with the transferable objects. + */ + send: T; + /** + * The objects to transfer. + */ + transferables: Transferable[]; +} + +/** + * + */ +function isTransferable(thing: any): thing is Transferable { + if (!thing || typeof thing !== 'object') return false; + // Don't check too thoroughly, since the list of transferable things in JS might grow over time + return true; +} + +/** + * + */ +export function isTransferDescriptor(thing: any): thing is TransferDescriptor { + return thing && typeof thing === 'object' && thing[$transferable]; +} + +/** + * Mark a transferable object as such, so it will no be serialized and + * deserialized on messaging with the main thread, but to transfer + * ownership of it to the receiving thread. + * + * Only works with array buffers, message ports and few more special + * types of objects, but it's much faster than serializing and + * deserializing them. + * + * Note: + * The transferable object cannot be accessed by this thread again + * unless the receiving thread transfers it back again! + * + * @param transferable - Array buffer, message port or similar. + * @see https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast + */ +export function Transfer(transferable: Transferable): TransferDescriptor; + +/** + * Mark transferable objects within an arbitrary object or array as + * being a transferable object. They will then not be serialized + * and deserialized on messaging with the main thread, but ownership + * of them will be tranferred to the receiving thread. + * + * Only array buffers, message ports and few more special types of + * objects can be transferred, but it's much faster than serializing and + * deserializing them. + * + * Note: + * The transferable object cannot be accessed by this thread again + * unless the receiving thread transfers it back again! + * + * @param transferable - Array buffer, message port or similar. + * @see https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast + */ +export function Transfer(payload: T, transferables: Transferable[]): TransferDescriptor; + +/** + * Create a transfer descriptor, marking these as transferable. + * @param payload - The payload. + * @param transferables - The transferable objects. + * @returns The descriptor. + */ +export function Transfer(payload: T, transferables?: Transferable[]): TransferDescriptor { + if (!transferables) { + if (!isTransferable(payload)) throw Error(); + transferables = [payload]; + } + + return { + [$transferable]: true, + send: payload, + transferables, + }; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/node/index.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/node/index.ts new file mode 100644 index 000000000000..cf87befc85e5 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/node/index.ts @@ -0,0 +1,2 @@ +export * from './node_connector.js'; +export * from './node_listener.js'; diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_connector.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_connector.ts new file mode 100644 index 000000000000..bf74c2a5d725 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_connector.ts @@ -0,0 +1,18 @@ +import { Worker } from 'worker_threads'; +import { Connector } from '../interface/connector.js'; +import { NodeConnectorSocket } from './node_connector_socket.js'; + +/** + * Creates sockets backed by a Node worker. + */ +export class NodeConnector implements Connector { + constructor(private worker: Worker) {} + + /** + * Creates a socket backed by a node worker. + * @returns The socket. + */ + createSocket() { + return Promise.resolve(new NodeConnectorSocket(this.worker)); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_connector_socket.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_connector_socket.ts new file mode 100644 index 000000000000..39b1b2e04b49 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_connector_socket.ts @@ -0,0 +1,36 @@ +import { TransferListItem, Worker } from 'worker_threads'; +import { Socket } from '../interface/socket.js'; + +/** + * A socket implementation using a Node worker. + */ +export class NodeConnectorSocket implements Socket { + constructor(private worker: Worker) {} + + /** + * Send a message. + * @param msg - The message. + * @param transfer - Objects to transfer ownership of. + * @returns A void promise. + */ + send(msg: any, transfer: Transferable[] = []): Promise { + this.worker.postMessage(msg, transfer as TransferListItem[]); + return Promise.resolve(); + } + + /** + * Register a message handler. + * @param cb - The handler function. + */ + registerHandler(cb: (msg: any) => any): void { + this.worker.on('message', cb); + } + + /** + * Remove all listeners from our worker. + */ + close() { + void this.send(undefined); + this.worker.removeAllListeners(); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_listener.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_listener.ts new file mode 100644 index 000000000000..92c753410fb8 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_listener.ts @@ -0,0 +1,25 @@ +import { parentPort } from 'worker_threads'; +import EventEmitter from 'events'; +import { Listener } from '../interface/listener.js'; +import { NodeListenerSocket } from './node_listener_socket.js'; + +/** + * A socket listener that works with Node. + */ +export class NodeListener extends EventEmitter implements Listener { + constructor() { + super(); + } + + /** + * Open the listener. + */ + open() { + this.emit('new_socket', new NodeListenerSocket(parentPort as any)); + } + + /** + * Close the listener. + */ + close() {} +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_listener_socket.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_listener_socket.ts new file mode 100644 index 000000000000..d492d45c6022 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/node/node_listener_socket.ts @@ -0,0 +1,37 @@ +import { MessagePort, TransferListItem } from 'worker_threads'; +import { Socket } from '../interface/socket.js'; + +/** + * An implementation of a TransportSocket using MessagePorts. + */ +export class NodeListenerSocket implements Socket { + constructor(private port: MessagePort) {} + + /** + * Send a message over this port. + * @param msg - The message. + * @param transfer - Transferable objects. + * @returns A void promise. + */ + send(msg: any, transfer: Transferable[] = []): Promise { + this.port.postMessage(msg, transfer as TransferListItem[]); + return Promise.resolve(); + } + + /** + * Add a handler to this port. + * @param cb - The handler function. + */ + registerHandler(cb: (msg: any) => any): void { + this.port.on('message', cb); + } + + /** + * Close this socket. + */ + close() { + void this.send(undefined); + this.port.removeAllListeners(); + this.port.close(); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/transport_client.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/transport_client.ts new file mode 100644 index 000000000000..9140f199a7d1 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/transport_client.ts @@ -0,0 +1,114 @@ +import { createDebugLogger } from "@aztec/foundation"; +import EventEmitter from "events"; +import { + EventMessage, + isEventMessage, + ResponseMessage, +} from "./dispatch/messages.js"; +import { Connector } from "./interface/connector.js"; +import { Socket } from "./interface/socket.js"; + +const debug = createDebugLogger("aztec:transport_client"); + +/** + * A pending request. + */ +interface PendingRequest { + /** + * The message ID. + */ + msgId: number; + resolve(data: any): void; + reject(error: Error): void; +} + +/** + * Augments the TransportClient class with more precise EventEmitter types. + */ +export interface TransportClient extends EventEmitter { + on(name: "event_msg", handler: (payload: Payload) => void): this; + emit(name: "event_msg", payload: Payload): boolean; +} + +/** + * A TransportClient provides a request/response and event api to a corresponding TransportServer. + * If `broadcast` is called on TransportServer, TransportClients will emit an `event_msg`. + * The `request` method will block until a response is returned from the TransportServer's dispatch function. + * Request multiplexing is supported. + */ +export class TransportClient extends EventEmitter { + private msgId = 0; + private pendingRequests: PendingRequest[] = []; + private socket?: Socket; + + constructor(private transportConnect: Connector) { + super(); + } + + /** + * Create and register our socket using our Connector. + */ + async open() { + this.socket = await this.transportConnect.createSocket(); + this.socket.registerHandler((msg) => this.handleSocketMessage(msg)); + } + + /** + * Close this and stop listening for messages. + */ + close() { + this.socket?.close(); + this.socket = undefined; + this.removeAllListeners(); + } + + /** + * Queue a request. + * @param payload - The request payload. + * @param transfer - Objects to transfer ownership of. + * @returns A promise of the query result. + */ + request(payload: Payload, transfer?: Transferable[]) { + if (!this.socket) { + throw new Error("Socket not open."); + } + const msgId = this.msgId++; + const msg = { msgId, payload }; + debug(`->`, msg); + return new Promise((resolve, reject) => { + this.pendingRequests.push({ resolve, reject, msgId }); + this.socket!.send(msg, transfer).catch(reject); + }); + } + + /** + * Handle an incoming socket message. + * @param msg - The message. + */ + private handleSocketMessage( + msg: ResponseMessage | EventMessage | undefined + ) { + if (msg === undefined) { + // The remote socket closed. + this.close(); + return; + } + debug(`<-`, msg); + if (isEventMessage(msg)) { + this.emit("event_msg", msg.payload); + return; + } + const reqIndex = this.pendingRequests.findIndex( + (r) => r.msgId === msg.msgId + ); + if (reqIndex === -1) { + return; + } + const [pending] = this.pendingRequests.splice(reqIndex, 1); + if (msg.error) { + pending.reject(new Error(msg.error)); + } else { + pending.resolve(msg.payload); + } + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/transport/transport_server.ts b/yarn-project/.yalc/@aztec/wasm/src/transport/transport_server.ts new file mode 100644 index 000000000000..0cb5aecf7e20 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/transport/transport_server.ts @@ -0,0 +1,96 @@ +import { RequestMessage, ResponseMessage } from './dispatch/messages.js'; +import { Listener } from './interface/listener.js'; +import { Socket } from './interface/socket.js'; +import { isTransferDescriptor } from './interface/transferable.js'; + +/** + * Keeps track of clients, providing a broadcast, and request/response api with multiplexing. + */ +export class TransportServer { + private sockets: Socket[] = []; + + constructor(private listener: Listener, private msgHandlerFn: (msg: Payload) => Promise) {} + + /** + * Start accepting new connections. + */ + start() { + this.listener.on('new_socket', client => this.handleNewSocket(client)); + this.listener.open(); + } + + /** + * Stops accepting new connections. It doesn't close existing sockets. + * It's expected the clients will gracefully complete by closing their end, sending an `undefined` message. + */ + stop() { + this.listener.close(); + } + + /** + * Broadcast a message. + * @param msg - The message. + */ + async broadcast(msg: Payload) { + await Promise.all(this.sockets.map(s => s.send({ payload: msg }))); + } + + /** + * New socket registration. + * @param socket - The socket to register. + */ + private handleNewSocket(socket: Socket) { + socket.registerHandler(async msg => { + if (msg === undefined) { + // Client socket has closed. Remove it from the list of sockets. Call close on it for any cleanup. + const socketIndex = this.sockets.findIndex(s => s === socket); + const [closingSocket] = this.sockets.splice(socketIndex, 1); + closingSocket.close(); + return; + } + return await this.handleSocketMessage(socket, msg); + }); + this.sockets.push(socket); + } + + /** + * Detect the 'transferables' argument to our socket from our message + * handler return type. + * @param data - The return object. + * @returns - The data and the. + */ + private getPayloadAndTransfers(data: any): [any, Transferable[]] { + if (isTransferDescriptor(data)) { + // We treat PayloadWithTransfers specially so that we're able to + // attach transferables while keeping a simple return-type based usage + return [data.send, data.transferables]; + } + if (data instanceof Uint8Array) { + // We may want to devise a better solution to this. We maybe given a view over a non cloneable/transferrable + // ArrayBuffer (such as a view over wasm memory). In this case we want to take a copy, and then transfer it. + const respPayload = data instanceof Uint8Array && ArrayBuffer.isView(data) ? new Uint8Array(data) : data; + const transferables = data instanceof Uint8Array ? [respPayload.buffer] : []; + return [respPayload, transferables]; + } + return [data, []]; + } + /** + * Handles a socket message from a listener. + * @param socket - The socket. + * @param requestMessage - The message to handle. + * @returns The socket response. + */ + private async handleSocketMessage(socket: Socket, { msgId, payload }: RequestMessage) { + try { + const data = await this.msgHandlerFn(payload); + + const [respPayload, transferables] = this.getPayloadAndTransfers(data); + const rep: ResponseMessage = { msgId, payload: respPayload }; + + await socket.send(rep, transferables); + } catch (err: any) { + const rep: ResponseMessage = { msgId, error: err.stack }; + await socket.send(rep); + } + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/wasm/async_call_state.ts b/yarn-project/.yalc/@aztec/wasm/src/wasm/async_call_state.ts new file mode 100644 index 000000000000..17554f4889da --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/wasm/async_call_state.ts @@ -0,0 +1,136 @@ +import { WasmModule } from './wasm_module.js'; + +/** + * The state of an asynchronous WASM function. + */ +export interface AsyncFnState { + /** + * Is this a contination? + */ + continuation: boolean; + /** + * A result, if one exists. + */ + result?: any; +} + +/** + * To enable asynchronous callbacks from wasm to js, we leverage asyncify. + * Https://kripken.github.io/blog/wasm/2019/07/16/asyncify.html. + * + * This class holds state and logic specific to handling async calls from wasm to js. + * A single instance of this class is instantiated as part of BarretenbergWasm. + * It allocates some memory for the asyncify stack data and initialises it. + * + * To make an async call into the wasm, just call `call` the same as in BarretenbergWasm, only it returns a promise. + * + * To make an async import that will be called from the wasm, wrap a function with the signature: + * my_func(state: AsyncFnState, ...args) + * with a call to `wrapImportFn`. + * The arguments are whatever the original call arguments were. The addition of AsyncFnState as the first argument + * allows for the detection of wether the function is continuing after the the async call has completed. + * If `state.continuation` is false, the function should start its async operation and return the promise. + * If `state.continuation` is true, the function can get the result from `state.result` perform any finalisation, + * and return an (optional) value to the wasm. + */ +export class AsyncCallState { + private ASYNCIFY_DATA_SIZE = 16 * 1024; + private asyncifyDataAddr!: number; + private asyncPromise?: Promise; + private wasm!: WasmModule; + private state?: AsyncFnState; + private callExport!: (...args: any[]) => number; + + /** + * Initialize the call hooks with a WasmModule. + * @param wasm - The module. + */ + public init(wasm: WasmModule) { + this.wasm = wasm; + this.callExport = (name: string, ...args: any[]) => wasm.call(name, ...args); + // Allocate memory for asyncify stack data. + this.asyncifyDataAddr = this.callExport('bbmalloc', this.ASYNCIFY_DATA_SIZE); + // TODO: is this view construction problematic like in WasmModule? + const view = new Uint32Array(wasm.getRawMemory().buffer); + // First two integers of asyncify data, are the start and end of the stack region. + view[this.asyncifyDataAddr >> 2] = this.asyncifyDataAddr + 8; + view[(this.asyncifyDataAddr + 4) >> 2] = this.asyncifyDataAddr + this.ASYNCIFY_DATA_SIZE; + } + + /** + * Log a message. + * @param args - The message arguments. + */ + private debug(...args: any[]) { + this.wasm.getLogger()(...args); + } + + /** + * Free the data associated with async call states. + */ + public destroy() { + // Free call stack data. + this.callExport('bbfree', this.asyncifyDataAddr); + } + + /** + * We call the wasm function, that will in turn call back into js via callImport and set this.asyncPromise and + * enable the instrumented "record stack unwinding" code path. + * Once the stack has unwound out of the wasm call, we enter into a loop of resolving the promise set in the call + * to callImport, and calling back into the wasm to rewind the stack and continue execution. + * @param name - The function name. + * @param args - The function args. + * @returns The function result. + */ + public async call(name: string, ...args: any) { + if (this.state) { + throw new Error(`Can only handle one async call at a time: ${name}(${args})`); + } + this.state = { continuation: false }; + let result = this.callExport(name, ...args); + + while (this.asyncPromise) { + // Disable the instrumented "record stack unwinding" code path. + this.callExport('asyncify_stop_unwind'); + this.debug('stack unwound.'); + // Wait for the async work to complete. + this.state.result = await this.asyncPromise; + this.state.continuation = true; + this.debug('result set starting rewind.'); + // Enable "stack rewinding" code path. + this.callExport('asyncify_start_rewind', this.asyncifyDataAddr); + // Call function again to rebuild the stack, and continue where we left off. + result = this.callExport(name, ...args); + } + + // Cleanup + this.state = undefined; + + return result; + } + + /** + * Wrap a WASM import function. + * @param fn - The function. + * @returns A wrapped version with asyncify calls. + */ + public wrapImportFn(fn: (state: AsyncFnState, ...args: any[]) => any) { + return (...args: any[]) => { + if (!this.asyncPromise) { + // We are in the normal code path. Start the async fetch of data. + this.asyncPromise = fn(this.state!, ...args); + // Enable "record stack unwinding" code path and return. + this.callExport('asyncify_start_unwind', this.asyncifyDataAddr); + } else { + // We are in the stack rewind code path, called once the promise is resolved. + // Save the result data back to the wasm, disable stack rewind code paths, and return. + this.callExport('asyncify_stop_rewind'); + const result = fn(this.state!, ...args); + // Cleanup. + this.asyncPromise = undefined; + this.state = { continuation: false }; + return result; + } + }; + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/wasm/empty_wasi_sdk.ts b/yarn-project/.yalc/@aztec/wasm/src/wasm/empty_wasi_sdk.ts new file mode 100644 index 000000000000..36ccfd3e0ec9 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/wasm/empty_wasi_sdk.ts @@ -0,0 +1,63 @@ +import { createDebugLogger } from "@aztec/foundation"; + +/** + * Dummy implementation of a necessary part of the wasi api: + * https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md + * We don't use these functions, but the environment expects them. + * TODO find a way to update off of wasi 12. + */ +/* eslint-disable camelcase */ +/* eslint-disable jsdoc/require-jsdoc */ +export const getEmptyWasiSdk = ( + debug = createDebugLogger("wasm:empty_wasi_sdk") +) => ({ + clock_time_get() { + debug("clock_time_get"); + }, + environ_get() { + debug("environ_get"); + }, + environ_sizes_get() { + debug("environ_sizes_get"); + }, + fd_close() { + debug("fd_close"); + }, + fd_read() { + debug("fd_read"); + }, + fd_write() { + debug("fd_write"); + }, + fd_seek() { + debug("fd_seek"); + }, + fd_fdstat_get() { + debug("fd_fdstat_get"); + }, + fd_fdstat_set_flags() { + debug("fd_fdstat_set_flags"); + }, + fd_prestat_get() { + debug("fd_prestat_get"); + return 8; + }, + fd_prestat_dir_name() { + debug("fd_prestat_dir_name"); + return 28; + }, + path_open() { + debug("path_open"); + }, + path_filestat_get() { + debug("path_filestat_get"); + }, + proc_exit() { + debug("proc_exit"); + return 52; + }, + random_get() { + debug("random_get"); + return 1; + }, +}); diff --git a/yarn-project/.yalc/@aztec/wasm/src/wasm/index.ts b/yarn-project/.yalc/@aztec/wasm/src/wasm/index.ts new file mode 100644 index 000000000000..2fb5a8b9afeb --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/wasm/index.ts @@ -0,0 +1,2 @@ +export { AsyncCallState, AsyncFnState } from './async_call_state.js'; +export { WasmModule } from './wasm_module.js'; diff --git a/yarn-project/.yalc/@aztec/wasm/src/wasm/wasm_module.test.ts b/yarn-project/.yalc/@aztec/wasm/src/wasm/wasm_module.test.ts new file mode 100644 index 000000000000..63c73a88c81c --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/wasm/wasm_module.test.ts @@ -0,0 +1,27 @@ +import { WasmModule } from './wasm_module.js'; +import { fileURLToPath } from 'url'; +import { readFile } from 'fs/promises'; +import { dirname } from 'path'; + +/** + * Fetch a simple WASM. + */ +async function fetchCode() { + const __dirname = dirname(fileURLToPath(import.meta.url)); + return await readFile(`${__dirname}/../test/gcd.wasm`); +} + +describe('barretenberg wasm', () => { + let wasm!: WasmModule; + + beforeAll(async () => { + wasm = new WasmModule(await fetchCode(), () => ({ + /*no imports*/ + })); + await wasm.init(); + }); + + it('should call gcd with correct result', () => { + expect(wasm.call('gcd', 12312, 12123)).toBe(27); + }); +}); diff --git a/yarn-project/.yalc/@aztec/wasm/src/wasm/wasm_module.ts b/yarn-project/.yalc/@aztec/wasm/src/wasm/wasm_module.ts new file mode 100644 index 000000000000..890ed1d5b893 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/wasm/wasm_module.ts @@ -0,0 +1,226 @@ +import { createDebugLogger, DebugLogger } from "@aztec/foundation"; +import { Buffer } from "buffer"; +import { MemoryFifo } from "../memory_fifo.js"; +import { getEmptyWasiSdk } from "./empty_wasi_sdk.js"; +import { randomBytes } from "crypto"; + +/** + * WasmModule: + * Helper over a webassembly module. + * Assumes a few quirks. + * 1) the module expects wasi_snapshot_preview1 with the methods from getEmptyWasiSdk + * 2) of which the webassembly + * we instantiate only uses random_get (update this if more WASI sdk methods are needed). + */ +export class WasmModule { + private memory!: WebAssembly.Memory; + private heap!: Uint8Array; + private instance?: WebAssembly.Instance; + private mutexQ = new MemoryFifo(); + private debug: DebugLogger; + + /** + * Create a wasm module. Should be followed by await init();. + * @param module - The module as a WebAssembly.Module or a Buffer. + * @param importFn - Imports expected by the WASM. + * @param loggerName - Optional, for debug logging. + */ + constructor( + private module: WebAssembly.Module | Buffer, + private importFn: (module: WasmModule) => any, + loggerName = "wasm" + ) { + this.debug = createDebugLogger(loggerName); + this.mutexQ.put(true); + } + + /** + * Return the wasm source. + * @returns The source. + */ + public getModule(): WebAssembly.Module | Buffer { + return this.module; + } + /** + * Initialize this wasm module. + * @param wasmImportEnv - Linked to a module called "env". Functions implementations referenced from e.g. C++. + * @param initial - 20 pages by default. 20*2**16 \> 1mb stack size plus other overheads. + * @param maximum - 8192 maximum by default. 512mb. + */ + public async init(initial = 20, maximum = 8192) { + this.debug( + `initial mem: ${initial} pages, ${ + (initial * 2 ** 16) / (1024 * 1024) + }mb. max mem: ${maximum} pages, ${(maximum * 2 ** 16) / (1024 * 1024)}mb` + ); + this.memory = new WebAssembly.Memory({ initial, maximum }); + // Create a view over the memory buffer. + // We do this once here, as webkit *seems* bugged out and actually shows this as new memory, + // thus displaying double. It's only worse if we create views on demand. I haven't established yet if + // the bug is also exasperating the termination on mobile due to "excessive memory usage". It could be + // that the OS is actually getting an incorrect reading in the same way the memory profiler does... + // The view will have to be recreated if the memory is grown. See getMemory(). + this.heap = new Uint8Array(this.memory.buffer); + + // We support the wasi 12 SDK, but only implement random_get + /* eslint-disable camelcase */ + const importObj = { + wasi_snapshot_preview1: { + ...getEmptyWasiSdk(this.debug), + random_get: (arr: number, length: number) => { + arr = arr >>> 0; + const heap = this.getMemory(); + const randomData = randomBytes(length); + for (let i = arr; i < arr + length; ++i) { + heap[i] = randomData[i - arr]; + } + }, + }, + env: this.importFn(this), + }; + + if (this.module instanceof WebAssembly.Module) { + this.instance = await WebAssembly.instantiate(this.module, importObj); + } else { + const { instance } = await WebAssembly.instantiate( + this.module, + importObj + ); + this.instance = instance; + } + } + + /** + * The methods or objects exported by the WASM module. + * @returns An indexable object. + */ + public exports(): any { + if (!this.instance) { + throw new Error("WasmModule: not initialized!"); + } + return this.instance.exports; + } + + /** + * Get the current logger. + * @returns Logging function. + */ + public getLogger() { + return this.debug; + } + + /** + * Add a logger. + * @param logger - Function to call when logging. + */ + public addLogger(logger: DebugLogger) { + const oldDebug = this.debug; + this.debug = (...args: any[]) => { + logger(...args); + oldDebug(...args); + }; + } + + /** + * Calls into the WebAssembly. + * @param name - The method name. + * @param args - The arguments to the method. + * @returns The numeric method result. + */ + public call(name: string, ...args: any): number { + if (!this.exports()[name]) { + throw new Error(`WASM function ${name} not found.`); + } + try { + // When returning values from the WASM, use >>> operator to convert + // signed representation to unsigned representation. + return this.exports()[name](...args) >>> 0; + } catch (err: any) { + const message = `WASM function ${name} aborted, error: ${err}`; + this.debug(message); + this.debug(err.stack); + throw new Error(message); + } + } + /** + * Get the memory used by the WASM module. + * @returns A WebAssembly memory object. + */ + public getRawMemory(): WebAssembly.Memory { + return this.memory; + } + /** + * Get the memory used by the WASM module, as a byte array. + * @returns A Uint8Array view of the WASM module memory. + */ + public getMemory(): Uint8Array { + // If the memory is grown, our view over it will be lost. Recreate the view. + if (this.heap.length === 0) { + this.heap = new Uint8Array(this.memory.buffer); + } + return this.heap; + } + + /** + * The memory size in bytes. + * @returns Number of bytes. + */ + public memSize(): number { + return this.getMemory().length; + } + + /** + * Get a slice of memory between two addresses. + * @param start - The start address. + * @param end - The end address. + * @returns A Uint8Array view of memory. + */ + public getMemorySlice(start: number, end: number) { + return this.getMemory().slice(start, end); + } + + /** + * Write data into the heap. + * @param offset - The address to write data at. + * @param arr - The data to write. + */ + public writeMemory(offset: number, arr: Uint8Array) { + const mem = this.getMemory(); + for (let i = 0; i < arr.length; i++) { + mem[i + offset] = arr[i]; + } + } + + /** + * Read WASM memory as a JS string. + * @param addr - The memory address. + * @returns A JS string. + */ + public getMemoryAsString(addr: number) { + addr = addr >>> 0; + const m = this.getMemory(); + let i = addr; + for (; m[i] !== 0; ++i); + return Buffer.from(m.slice(addr, i)).toString("ascii"); + } + + /** + * When calling the wasm, sometimes a caller will require exclusive access over a series of calls. + * E.g. When a result is written to address 0, one cannot have another caller writing to the same address via + * writeMemory before the result is read via sliceMemory. + * Acquire() gets a single token from a fifo. The caller must call release() to add the token back. + */ + public async acquire() { + await this.mutexQ.get(); + } + + /** + * Release the mutex, letting another promise call acquire(). + */ + public release() { + if (this.mutexQ.length() !== 0) { + throw new Error("Release called but not acquired."); + } + this.mutexQ.put(true); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/browser/index.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/browser/index.ts new file mode 100644 index 000000000000..ae6a02c0771b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/browser/index.ts @@ -0,0 +1,2 @@ +export * from './web_worker.js'; +export * from './web_data_store.js'; diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/browser/start_web_module.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/browser/start_web_module.ts new file mode 100644 index 000000000000..e6b05bbd3657 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/browser/start_web_module.ts @@ -0,0 +1,23 @@ +import { DispatchMsg, TransportServer, WorkerListener } from '../../transport/index.js'; +import { WasmModule } from '../../wasm/wasm_module.js'; + +/** + * Start the transport server corresponding to this module. + * @param module - The WasmModule to host. + */ +export function startWebModule(module: WasmModule) { + const dispatch = async ({ fn, args }: DispatchMsg) => { + if (fn === '__destroyWorker__') { + transportServer.stop(); + return; + } + if (!(module as any)[fn]) { + throw new Error(`dispatch error, function not found: ${fn}`); + } + return await (module as any)[fn](...args); + }; + const transportListener = new WorkerListener(self); + const transportServer = new TransportServer(transportListener, dispatch); + module.addLogger((...args: any[]) => transportServer.broadcast({ fn: 'emit', args: ['log', ...args] })); + transportServer.start(); +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/browser/web_data_store.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/browser/web_data_store.ts new file mode 100644 index 000000000000..79f9c6a60eb0 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/browser/web_data_store.ts @@ -0,0 +1,37 @@ +import { DataStore } from '../data_store.js'; +import levelup, { LevelUp } from 'levelup'; +import memdown from 'memdown'; + +/** + * Cache for data used by wasm module. + * Stores in a LevelUp database. + */ +export class WebDataStore implements DataStore { + private db: LevelUp; + + constructor() { + // TODO: The whole point of this is to reduce memory load in the browser. + // Replace with leveljs so the data is stored in indexeddb and not in memory. + // Hack: Cast as any to work around package "broken" with node16 resolution + // See https://github.com/microsoft/TypeScript/issues/49160 + this.db = levelup((memdown as any)()); + } + + /** + * Lookup a key. + * @param key - Key to lookup. + * @returns The buffer. + */ + async get(key: string): Promise { + return await this.db.get(key).catch(() => {}); + } + + /** + * Alter a key. + * @param key - Key to alter. + * @param value - Buffer to store. + */ + async set(key: string, value: Buffer): Promise { + await this.db.put(key, value); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/browser/web_worker.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/browser/web_worker.ts new file mode 100644 index 000000000000..2f62882d4d8c --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/browser/web_worker.ts @@ -0,0 +1,24 @@ +import { WasmModule } from '../../wasm/wasm_module.js'; +import { createDispatchProxy, DispatchMsg, TransportClient, WorkerConnector } from '../../transport/index.js'; +import { WasmWorker } from '../wasm_worker.js'; + +/** + * Instantiate a web worker. + * @param url - The URL. + * @param initialMem - Initial memory pages. + * @param maxMem - Maximum memory pages. + * @returns The worker. + */ +export async function createWebWorker(url: string, initialMem?: number, maxMem?: number): Promise { + const worker = new Worker(url); + const transportConnect = new WorkerConnector(worker); + const transportClient = new TransportClient(transportConnect); + await transportClient.open(); + const remoteModule = createDispatchProxy(WasmModule, transportClient) as WasmWorker; + remoteModule.destroyWorker = async () => { + await transportClient.request({ fn: '__destroyWorker__', args: [] }); + transportClient.close(); + }; + await remoteModule.init(initialMem, maxMem); + return remoteModule; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/data_store.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/data_store.ts new file mode 100644 index 000000000000..4390b2775eeb --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/data_store.ts @@ -0,0 +1,7 @@ +/** + * Simple read/write interface for wasm modules. + */ +export interface DataStore { + get(key: string): Promise; + set(key: string, value: Buffer): Promise; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/index.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/index.ts new file mode 100644 index 000000000000..de4da3527516 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/index.ts @@ -0,0 +1,2 @@ +export { WorkerPool } from './worker_pool.js'; +export { WasmWorker } from './wasm_worker.js'; diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/node/index.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/node/index.ts new file mode 100644 index 000000000000..6ac2cfb6ba37 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/node/index.ts @@ -0,0 +1,2 @@ +export * from './node_worker.js'; +export * from './node_data_store.js'; diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/node/node_data_store.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/node/node_data_store.ts new file mode 100644 index 000000000000..d3835350c30e --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/node/node_data_store.ts @@ -0,0 +1,36 @@ +import { DataStore } from '../data_store.js'; +import levelup, { LevelUp } from 'levelup'; +import leveldown from 'leveldown'; +import memdown from 'memdown'; + +/** + * Cache for data used by wasm module. + */ +export class NodeDataStore implements DataStore { + private db: LevelUp; + + // eslint-disable-next-line + constructor(path?: string) { + // Hack: Cast as any to work around packages "broken" with node16 resolution + // See https://github.com/microsoft/TypeScript/issues/49160 + this.db = levelup(path ? (leveldown as any)(path) : (memdown as any)()); + } + + /** + * Get a value from our DB. + * @param key - The key to look up. + * @returns The value. + */ + async get(key: string): Promise { + return await this.db.get(key).catch(() => {}); + } + + /** + * Set a value in our DB. + * @param key - The key to update. + * @param value - The value to set. + */ + async set(key: string, value: Buffer): Promise { + await this.db.put(key, value); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/node/node_worker.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/node/node_worker.ts new file mode 100644 index 000000000000..a11f379196ab --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/node/node_worker.ts @@ -0,0 +1,22 @@ +import { Worker } from 'worker_threads'; +import { createDispatchProxy, DispatchMsg, TransportClient } from '../../transport/index.js'; +import { NodeConnector } from '../../transport/index.js'; +import { WasmModule } from '../../wasm/wasm_module.js'; +import { WasmWorker } from '../wasm_worker.js'; + +/** + * + */ +export async function createNodeWorker(filepath: string, initialMem?: number, maxMem?: number): Promise { + const worker = new Worker(filepath); + const transportConnect = new NodeConnector(worker); + const transportClient = new TransportClient(transportConnect); + await transportClient.open(); + const remoteModule = createDispatchProxy(WasmModule, transportClient) as WasmWorker; + remoteModule.destroyWorker = async () => { + await transportClient.request({ fn: '__destroyWorker__', args: [] }); + transportClient.close(); + }; + await remoteModule.init(initialMem, maxMem); + return remoteModule; +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/node/start_node_module.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/node/start_node_module.ts new file mode 100644 index 000000000000..ca0c1c9fd9ef --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/node/start_node_module.ts @@ -0,0 +1,28 @@ +import { parentPort } from 'worker_threads'; +import { NodeListener, DispatchMsg, TransportServer } from '../../transport/index.js'; +import { WasmModule } from '../../wasm/wasm_module.js'; + +if (!parentPort) { + throw new Error('InvalidWorker'); +} + +/** + * Start the transport server corresponding to this module. + * @param module - The WasmModule to host. + */ +export function startNodeModule(module: WasmModule) { + const dispatch = async ({ fn, args }: DispatchMsg) => { + if (fn === '__destroyWorker__') { + transportServer.stop(); + return; + } + if (!(module as any)[fn]) { + throw new Error(`dispatch error, function not found: ${fn}`); + } + return await (module as any)[fn](...args); + }; + const transportListener = new NodeListener(); + const transportServer = new TransportServer(transportListener, dispatch); + module.addLogger((...args: any[]) => transportServer.broadcast({ fn: 'emit', args: ['log', ...args] })); + transportServer.start(); +} diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/wasm_worker.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/wasm_worker.ts new file mode 100644 index 000000000000..a9dcb4a7ad27 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/wasm_worker.ts @@ -0,0 +1,7 @@ +import { Proxify } from '../transport/index.js'; +import { WasmModule } from '../wasm/wasm_module.js'; + +/** + * Represents either a WASM web worker, or node.js worker. + */ +export type WasmWorker = Proxify & { destroyWorker(): void }; diff --git a/yarn-project/.yalc/@aztec/wasm/src/worker/worker_pool.ts b/yarn-project/.yalc/@aztec/wasm/src/worker/worker_pool.ts new file mode 100644 index 000000000000..04d2a2eba604 --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/src/worker/worker_pool.ts @@ -0,0 +1,87 @@ +import { createDebugLogger } from "@aztec/foundation"; +import { WasmWorker } from "./wasm_worker.js"; + +const debug = createDebugLogger("bb:worker_pool"); + +/** + * Type of a worker factory. + * Used to customize WorkerPool worker construction. + */ +export type CreateWorker = ( + name: string, + minMem: number, + maxMem: number +) => WasmWorker; +/** + * Allocates a pool of WasmWorker's. + * Worker 0 is allocated MAX_PAGES memory pages. This is because worker 0 will need to hold the proving key + * (i.e. Has state), whereas the others are pure compute (they hold a little crs state). + */ +export class WorkerPool { + // TODO(AD): Revisit what this means in aztec 3 context + // -- + // Introduction of low mem prover work (polynomial cache) may actually increase mem usage when the backing store isn't + // enabled. We were seeing intermittent failings related to memory in production for some users when limiting to + // 6660 (416MB). It would be nice to understand why this is (the non determinism and/or the increased mem usage). + // For now, increasing mem usage to 512MB. This maybe preferable to backing out the low mem work, but + // ironically may break the chance of us using it in mobile. + // We *could* enable the low memory backing store, but this needs a little bit of work to actually + // read/write from indexeddb, performance testing, and actual further memory load testing. + // At this point it's hard to know what our memory savings would be relative to just fully reverting the LMP. + // public static MAX_PAGES = 6660; + /** + * The maximum number of memory pages to be used by the webassembly. + */ + public static MAX_PAGES = 8192; + /** + * The workers in the pool. + */ + private workers: WasmWorker[] = []; + + /** + * Create an instance and initialize the workers. + * @param createWorker - Worker factory. + * @param poolSize - Pool size. + * @returns An initialized WorkerPool. + */ + static async new(createWorker: CreateWorker, poolSize: number) { + const pool = new WorkerPool(); + await pool.init(createWorker, poolSize); + return pool; + } + + /** + * Initialize the workers. + * @param createWorker - Worker factory(). + * @param poolSize - Pool size. + * @param maxMem - Max memory pages. + */ + public async init( + createWorker: CreateWorker, + poolSize: number, + maxMem = WorkerPool.MAX_PAGES + ) { + debug(`creating ${poolSize} workers...`); + const start = new Date().getTime(); + this.workers = await Promise.all( + Array(poolSize) + .fill(0) + .map((_, i) => + createWorker( + `${i}`, + i === 0 ? Math.min(WorkerPool.MAX_PAGES, maxMem) : 768, + maxMem + ) + ) + ); + + debug(`created workers: ${new Date().getTime() - start}ms`); + } + + /** + * Tell all workers in the pool to stop processing. + */ + public async destroy() { + await Promise.all(this.workers.map((w) => w.destroyWorker())); + } +} diff --git a/yarn-project/.yalc/@aztec/wasm/tsconfig.dest.json b/yarn-project/.yalc/@aztec/wasm/tsconfig.dest.json new file mode 100644 index 000000000000..965aaa1c433e --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/tsconfig.dest.json @@ -0,0 +1,4 @@ +{ + "extends": ".", + "exclude": ["**/*.test.*", "**/fixtures/*"] +} diff --git a/yarn-project/.yalc/@aztec/wasm/tsconfig.json b/yarn-project/.yalc/@aztec/wasm/tsconfig.json new file mode 100644 index 000000000000..f67ddec9fd6b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "..", + "compilerOptions": { + "outDir": "dest", + "rootDir": "src", + "tsBuildInfoFile": ".tsbuildinfo" + }, + "include": ["src"] +} diff --git a/yarn-project/.yalc/@aztec/wasm/yalc.sig b/yarn-project/.yalc/@aztec/wasm/yalc.sig new file mode 100644 index 000000000000..924c15826a5b --- /dev/null +++ b/yarn-project/.yalc/@aztec/wasm/yalc.sig @@ -0,0 +1 @@ +49e137843b2fae07ab3c4df8d2229740 \ No newline at end of file diff --git a/yarn-project/archiver/jest.integration.config.json b/yarn-project/archiver/jest.integration.config.json new file mode 100644 index 000000000000..f89093c1acff --- /dev/null +++ b/yarn-project/archiver/jest.integration.config.json @@ -0,0 +1,13 @@ +{ + "preset": "ts-jest/presets/default-esm", + "globals": { + "ts-jest": { + "useESM": true + } + }, + "moduleNameMapper": { + "^(\\.{1,2}/.*)\\.js$": "$1" + }, + "testRegex": "./test/.*\\.test\\.ts$", + "rootDir": "./test" +} \ No newline at end of file diff --git a/yarn-project/archiver/package.json b/yarn-project/archiver/package.json index 97c491ebfbd1..95ab3f35d226 100644 --- a/yarn-project/archiver/package.json +++ b/yarn-project/archiver/package.json @@ -15,7 +15,10 @@ "start:dev": "tsc-watch -p tsconfig.dest.json --onSuccess 'yarn start'", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", - "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" + "formatting:fix": "run -T prettier -w ./src", + "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests", + "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"", + "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json" }, "jest": { "preset": "ts-jest/presets/default-esm", @@ -26,8 +29,10 @@ "rootDir": "./src" }, "dependencies": { + "@aztec/circuits.js": "workspace:^", "@aztec/ethereum.js": "workspace:^", "@aztec/foundation": "workspace:^", + "@aztec/l1-contracts": "workspace:^", "debug": "^4.3.4", "tsc-watch": "^6.0.0", "tslib": "^2.5.0", @@ -41,7 +46,9 @@ "@types/jest": "^29.4.1", "@types/node": "^18.15.2", "@types/ws": "^8.5.4", + "concurrently": "^7.6.0", "jest": "^29.5.0", + "jest-mock-extended": "^3.0.4", "ts-jest": "^29.0.5", "ts-node": "^10.9.1", "typescript": "^4.9.5" diff --git a/yarn-project/archiver/src/abis/rollup.ts b/yarn-project/archiver/src/abis/rollup.ts deleted file mode 100644 index 3e4aa667373f..000000000000 --- a/yarn-project/archiver/src/abis/rollup.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const rollupAbi = [ - { - name: 'L2BlockProcessed', - type: 'event', - inputs: [{ type: 'uint256', name: 'blockNum', indexed: true }], - }, - { - inputs: [], - name: 'nextBlockNum', - outputs: [{ name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function', - }, -] as const; diff --git a/yarn-project/archiver/src/abis/yeeter.ts b/yarn-project/archiver/src/abis/yeeter.ts deleted file mode 100644 index bb9b966c04bc..000000000000 --- a/yarn-project/archiver/src/abis/yeeter.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { parseAbiItem } from 'viem'; - -export const yeeterAbi = [ - parseAbiItem('event Yeet(uint256 indexed blockNum, address indexed sender, bytes blabber)'), -] as const; diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 138e8575d479..90feb96df83f 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -1,38 +1,17 @@ import { EthAddress } from '@aztec/ethereum.js/eth_address'; +import { RollupAbi, YeeterAbi } from '@aztec/l1-contracts/viem'; import { jest } from '@jest/globals'; -import { PublicClient } from 'viem'; -import { Archiver } from './archiver.js'; - -jest.mock('viem'); +import { mock, MockProxy } from 'jest-mock-extended'; +import { encodeFunctionData, Log, PublicClient, toHex, Transaction } from 'viem'; +import { Archiver, mockRandomL2Block } from './archiver.js'; describe('Archiver', () => { const rollupAddress = '0x0000000000000000000000000000000000000000'; const yeeterAddress = '0x0000000000000000000000000000000000000000'; - let publicClient: PublicClient; + let publicClient: MockProxy; beforeEach(() => { - publicClient = { - readContract: jest.fn().mockReturnValue(3n), - createEventFilter: jest.fn(), - getFilterLogs: jest.fn().mockReturnValue([ - { - args: { - blockNum: 0n, - }, - }, - { - args: { - blockNum: 1n, - }, - }, - { - args: { - blockNum: 2n, - }, - }, - ]), - watchEvent: jest.fn().mockReturnValue(jest.fn()), - } as unknown as PublicClient; + publicClient = mock(); }); it('can start, sync and stop', async () => { @@ -41,24 +20,50 @@ describe('Archiver', () => { EthAddress.fromString(rollupAddress), EthAddress.fromString(yeeterAddress), ); - let syncStatus = await archiver.getSyncStatus(); + let latestBlockNum = await archiver.getLatestBlockNum(); - expect(syncStatus).toStrictEqual({ - syncedToBlock: -1, - latestBlock: 2, - }); - expect(latestBlockNum).toBe(syncStatus.syncedToBlock); + expect(latestBlockNum).toEqual(0); + + const rollupLogs = [1, 2, 3].map(makeRollupEvent); + const rollupTxs = [1, 2, 3].map(makeRollupTx); + const yeeterLogs = [] as Log[]; + + publicClient.getFilterLogs.mockResolvedValueOnce(rollupLogs).mockResolvedValueOnce(yeeterLogs); + rollupTxs.forEach(tx => publicClient.getTransaction.mockResolvedValueOnce(tx)); + publicClient.watchContractEvent.mockReturnValue(jest.fn()); await archiver.start(); - syncStatus = await archiver.getSyncStatus(); latestBlockNum = await archiver.getLatestBlockNum(); - expect(syncStatus).toStrictEqual({ - syncedToBlock: 2, - latestBlock: 2, - }); - expect(latestBlockNum).toBe(syncStatus.syncedToBlock); + expect(latestBlockNum).toEqual(3); await archiver.stop(); }); }); + +/** + * Makes a fake rollup event for testing purposes. + * @param blockNum - L2Block number. + * @returns A rollup event log. + */ +function makeRollupEvent(blockNum: number) { + return { args: { blockNum: BigInt(blockNum) }, transactionHash: `0x${blockNum}` } as unknown as Log< + bigint, + number, + undefined, + typeof RollupAbi, + 'L2BlockProcessed' + >; +} + +/** + * Makes a fake rollup tx for testing purposes. + * @param blockNum - L2Block number. + * @returns A fake tx with calldata that corresponds to calling process in the Rollup contract. + */ +function makeRollupTx(blockNum: number) { + const proof = `0x`; + const block = toHex(mockRandomL2Block(blockNum).encode()); + const input = encodeFunctionData({ abi: RollupAbi, functionName: 'process', args: [proof, block] }); + return { input } as Transaction; +} diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 33aa09e70d29..cf33a70cba34 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -1,12 +1,13 @@ -import { PublicClient, getAddress, http, createPublicClient } from 'viem'; -import { rollupAbi } from '../abis/rollup.js'; -import { yeeterAbi } from '../abis/yeeter.js'; -import { ContractData, L2Block } from '../l2_block/l2_block.js'; -import { randomAppendOnlyTreeSnapshot, randomContractData } from '../l2_block/mocks.js'; -import { L2BlockSource, L2BlockSourceSyncStatus } from '../l2_block/l2_block_source.js'; +import { fr, makeAppendOnlyTreeSnapshot, makeEthAddress } from '@aztec/circuits.js/factories'; import { EthAddress } from '@aztec/ethereum.js/eth_address'; +import { createDebugLogger } from '@aztec/foundation'; +import { RollupAbi, YeeterAbi } from '@aztec/l1-contracts/viem'; +import { createPublicClient, decodeFunctionData, getAddress, Hex, hexToBytes, http, Log, PublicClient } from 'viem'; import { localhost } from 'viem/chains'; -import { createDebugLogger, randomBytes } from '@aztec/foundation'; +import { ArchiverConfig } from './config.js'; +import { ContractData, L2Block } from '../l2_block/l2_block.js'; +import { L2BlockSource } from '../l2_block/l2_block_source.js'; +import { INITIAL_ROLLUP_ID } from '@aztec/l1-contracts'; /** * Pulls L2 blocks in a non-blocking manner and provides interface for their retrieval. @@ -31,45 +32,35 @@ export class Archiver implements L2BlockSource { * @param publicClient - A client for interacting with the Ethereum node. * @param rollupAddress - Ethereum address of the rollup contract. * @param yeeterAddress - Ethereum address of the yeeter contract. + * @param pollingInterval - The interval for polling for rollup events. * @param log - A logger. */ constructor( private readonly publicClient: PublicClient, private readonly rollupAddress: EthAddress, private readonly yeeterAddress: EthAddress, + private readonly pollingInterval = 10_000, private readonly log = createDebugLogger('aztec:archiver'), ) {} /** - * Creates a new instance of the Archiver. - * @param rpcUrl - The RPC url for connecting to an eth node. - * @param rollupAddress - Ethereum address of the rollup contract. - * @param yeeterAddress - Ethereum address of the yeeter contract. + * Creates a new instance of the Archiver and blocks until it syncs from chain. + * @param config - The archiver's desired configuration. * @returns - An instance of the archiver. */ - public static new(rpcUrl: string, rollupAddress: EthAddress, yeeterAddress: EthAddress) { + public static async createAndSync(config: ArchiverConfig) { const publicClient = createPublicClient({ chain: localhost, - transport: http(rpcUrl), - }); - return new Archiver(publicClient, rollupAddress, yeeterAddress); - } - - /** - * Gets the sync status of the L2 block source. - * @returns The sync status of the L2 block source. - */ - public async getSyncStatus(): Promise { - const nextBlockNum = await this.publicClient.readContract({ - address: getAddress(this.rollupAddress.toString()), - abi: rollupAbi, - functionName: 'nextBlockNum', + transport: http(config.rpcUrl), }); - - return { - syncedToBlock: await this.getLatestBlockNum(), - latestBlock: Number(nextBlockNum) - 1, - }; + const archiver = new Archiver( + publicClient, + config.rollupContract, + config.yeeterContract, + config.archiverPollingInterval, + ); + await archiver.start(); + return archiver; } /** @@ -79,6 +70,8 @@ export class Archiver implements L2BlockSource { this.log('Starting initial sync...'); await this.runInitialSync(); this.log('Initial sync finished.'); + // TODO: Any logs emitted between the initial sync and the start watching will be lost + // We should start watching before we start the initial sync this.startWatchingEvents(); this.log('Watching for new data...'); } @@ -87,39 +80,46 @@ export class Archiver implements L2BlockSource { * Fetches all the L2BlockProcessed and Yeet events since genesis and processes them. */ private async runInitialSync() { - const blockFilter = await this.publicClient.createEventFilter({ + const blockFilter = await this.publicClient.createContractEventFilter({ address: getAddress(this.rollupAddress.toString()), fromBlock: 0n, - event: rollupAbi[0], + abi: RollupAbi, + eventName: 'L2BlockProcessed', }); - const yeetFilter = await this.publicClient.createEventFilter({ + const yeetFilter = await this.publicClient.createContractEventFilter({ address: getAddress(this.yeeterAddress.toString()), - event: yeeterAbi[0], + abi: YeeterAbi, + eventName: 'Yeet', fromBlock: 0n, }); const blockLogs = await this.publicClient.getFilterLogs({ filter: blockFilter }); const yeetLogs = await this.publicClient.getFilterLogs({ filter: yeetFilter }); - this.processBlockLogs(blockLogs); + await this.processBlockLogs(blockLogs); this.processYeetLogs(yeetLogs); } /** * Starts a polling loop in the background which watches for new events and passes them to the respective handlers. + * TODO: Handle reorgs, consider using github.com/ethereumjs/ethereumjs-blockstream. */ private startWatchingEvents() { - this.unwatchBlocks = this.publicClient.watchEvent({ + this.unwatchBlocks = this.publicClient.watchContractEvent({ address: getAddress(this.rollupAddress.toString()), - event: rollupAbi[0], + abi: RollupAbi, + eventName: 'L2BlockProcessed', onLogs: logs => this.processBlockLogs(logs), + pollingInterval: this.pollingInterval, }); - this.unwatchYeets = this.publicClient.watchEvent({ + this.unwatchYeets = this.publicClient.watchContractEvent({ address: getAddress(this.yeeterAddress.toString()), - event: yeeterAbi[0], + abi: YeeterAbi, + eventName: 'Yeet', onLogs: logs => this.processYeetLogs(logs), + pollingInterval: this.pollingInterval, }); } @@ -127,19 +127,27 @@ export class Archiver implements L2BlockSource { * Processes newly received L2BlockProcessed events. * @param logs - L2BlockProcessed event logs. */ - private processBlockLogs(logs: any[]) { - this.log('Processed ' + logs.length + ' L2 blocks...'); + private async processBlockLogs(logs: Log[]) { for (const log of logs) { const blockNum = log.args.blockNum; - if (blockNum !== BigInt(this.l2Blocks.length)) { - throw new Error('Block number mismatch. Expected: ' + this.l2Blocks.length + ' but got: ' + blockNum + '.'); + if (blockNum !== BigInt(this.l2Blocks.length + INITIAL_ROLLUP_ID)) { + throw new Error( + 'Block number mismatch. Expected: ' + + (this.l2Blocks.length + INITIAL_ROLLUP_ID) + + ' but got: ' + + blockNum + + '.', + ); } - const newBlock = mockRandomL2Block(log.args.blockNum); - const yeet = this.pendingYeets.find(yeet => yeet.readUInt32BE(0) === blockNum); + // TODO: Fetch blocks from calldata in parallel + const newBlock = await this.getBlockFromCallData(log.transactionHash!, log.args.blockNum); + this.log(`Retrieved block ${newBlock.number} from chain`); + //this.log(`Processed new block: ${newBlock.inspect()}`); + const yeet = this.pendingYeets.find(yeet => BigInt(yeet.readUInt32BE(0)) === blockNum); if (yeet !== undefined) { newBlock.setYeet(yeet); // Remove yeet from pending - this.pendingYeets = this.pendingYeets.filter(yeet => yeet.readUInt32BE(0) !== blockNum); + this.pendingYeets = this.pendingYeets.filter(yeet => BigInt(yeet.readUInt32BE(0)) !== blockNum); } this.l2Blocks.push(newBlock); } @@ -149,21 +157,45 @@ export class Archiver implements L2BlockSource { * Processes newly received Yeet events. * @param logs - Yeet event logs. */ - private processYeetLogs(logs: any[]) { + private processYeetLogs(logs: Log[]) { for (const log of logs) { - const blockNum = log.args.blockNum; + const blockNum = log.args.l2blockNum; if (blockNum < BigInt(this.l2Blocks.length)) { - const block = this.l2Blocks[blockNum]; - block.setYeet(log.args.blabber); + const block = this.l2Blocks[Number(blockNum) - INITIAL_ROLLUP_ID]; + block.setYeet(Buffer.from(hexToBytes(log.args.blabber))); this.log('Enriched block ' + blockNum + ' with yeet.'); } else { - this.pendingYeets.push(log.args.blabber); + this.pendingYeets.push(Buffer.from(hexToBytes(log.args.blabber))); this.log('Added yeet with blockNum ' + blockNum + ' to pending list.'); } } this.log('Processed ' + logs.length + ' yeets...'); } + /** + * Builds an L2 block out of calldata from the tx that published it. + * Assumes that the block was published from an EOA. + * TODO: Add retries and error management. + * @param txHash - Hash of the tx that published it. + * @param l2BlockNum - L2 block number. + * @returns An L2 block deserialized from the calldata. + */ + private async getBlockFromCallData(txHash: `0x${string}`, l2BlockNum: bigint): Promise { + const { input: data } = await this.publicClient.getTransaction({ hash: txHash }); + // TODO: File a bug in viem who complains if we dont remove the ctor from the abi here + const { functionName, args } = decodeFunctionData({ + abi: RollupAbi.filter(item => item.type !== 'constructor'), + data, + }); + if (functionName !== 'process') throw new Error(`Unexpected method called ${functionName}`); + const [, l2blockHex] = args! as [Hex, Hex]; + const block = L2Block.decode(Buffer.from(hexToBytes(l2blockHex))); + if (BigInt(block.number) !== l2BlockNum) { + throw new Error(`Block number mismatch: expected ${l2BlockNum} but got ${block.number}`); + } + return block; + } + /** * Stops the archiver. * @returns A promise signalling completion of the stop process. @@ -183,19 +215,20 @@ export class Archiver implements L2BlockSource { /** * Gets the `take` amount of L2 blocks starting from `from`. - * @param from - If of the first rollup to return (inclusive). + * @param from - Id of the first rollup to return (inclusive). * @param take - The number of blocks to return. * @returns The requested L2 blocks. */ public getL2Blocks(from: number, take: number): Promise { + if (from < INITIAL_ROLLUP_ID) { + throw new Error(`Invalid block range ${from}`); + } if (from > this.l2Blocks.length) { return Promise.resolve([]); } - if (from + take > this.l2Blocks.length) { - return Promise.resolve(this.l2Blocks.slice(from)); - } - - return Promise.resolve(this.l2Blocks.slice(from, from + take)); + const startIndex = from - 1; + const endIndex = startIndex + take; + return Promise.resolve(this.l2Blocks.slice(startIndex, endIndex)); } /** @@ -203,7 +236,8 @@ export class Archiver implements L2BlockSource { * @returns The number of the latest L2 block processed by the block source implementation. */ public getLatestBlockNum(): Promise { - return Promise.resolve(this.l2Blocks.length - 1); + if (this.l2Blocks.length === 0) return Promise.resolve(INITIAL_ROLLUP_ID - 1); + return Promise.resolve(this.l2Blocks[this.l2Blocks.length - 1].number); } } @@ -213,23 +247,23 @@ export class Archiver implements L2BlockSource { * @returns Random L2Block. */ export function mockRandomL2Block(l2BlockNum: number): L2Block { - const newNullifiers = [randomBytes(32), randomBytes(32), randomBytes(32), randomBytes(32)]; - const newCommitments = [randomBytes(32), randomBytes(32), randomBytes(32), randomBytes(32)]; - const newContracts: Buffer[] = [randomBytes(32)]; - const newContractsData: ContractData[] = [randomContractData()]; + const newNullifiers = [fr(0x1), fr(0x2), fr(0x3), fr(0x4)]; + const newCommitments = [fr(0x101), fr(0x102), fr(0x103), fr(0x104)]; + const newContracts = [fr(0x201)]; + const newContractsData: ContractData[] = [new ContractData(fr(0x301), makeEthAddress(0x302))]; return new L2Block( l2BlockNum, - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(newCommitments.length), - randomAppendOnlyTreeSnapshot(newNullifiers.length), - randomAppendOnlyTreeSnapshot(newContracts.length), - randomAppendOnlyTreeSnapshot(1), - randomAppendOnlyTreeSnapshot(1), + makeAppendOnlyTreeSnapshot(0), + makeAppendOnlyTreeSnapshot(0), + makeAppendOnlyTreeSnapshot(0), + makeAppendOnlyTreeSnapshot(0), + makeAppendOnlyTreeSnapshot(0), + makeAppendOnlyTreeSnapshot(newCommitments.length), + makeAppendOnlyTreeSnapshot(newNullifiers.length), + makeAppendOnlyTreeSnapshot(newContracts.length), + makeAppendOnlyTreeSnapshot(1), + makeAppendOnlyTreeSnapshot(1), newCommitments, newNullifiers, newContracts, diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts new file mode 100644 index 000000000000..06d06036c23b --- /dev/null +++ b/yarn-project/archiver/src/archiver/config.ts @@ -0,0 +1,16 @@ +import { L1Addresses } from '@aztec/l1-contracts'; + +/** + * The archiver configuration. + */ +export interface ArchiverConfig extends L1Addresses { + /** + * The url of the Ethereum RPC node. + */ + rpcUrl: string; + + /** + * The polling interval in ms for retrieving new rollups. + */ + archiverPollingInterval?: number; +} diff --git a/yarn-project/archiver/src/archiver/index.ts b/yarn-project/archiver/src/archiver/index.ts index 661ac2ff02f5..201381aa0beb 100644 --- a/yarn-project/archiver/src/archiver/index.ts +++ b/yarn-project/archiver/src/archiver/index.ts @@ -1 +1,2 @@ export * from './archiver.js'; +export * from './config.js'; diff --git a/yarn-project/archiver/src/block_downloader/l2_block_downloader.ts b/yarn-project/archiver/src/block_downloader/l2_block_downloader.ts index f72abbf79df5..90f18fde0132 100644 --- a/yarn-project/archiver/src/block_downloader/l2_block_downloader.ts +++ b/yarn-project/archiver/src/block_downloader/l2_block_downloader.ts @@ -1,4 +1,5 @@ import { InterruptableSleep, Semaphore, MemoryFifo } from '@aztec/foundation'; +import { INITIAL_ROLLUP_ID } from '@aztec/l1-contracts'; import { L2BlockSource, L2Block } from '../index.js'; /** @@ -21,9 +22,9 @@ export class L2BlockDownloader { /** * Starts the downloader. - * @param from - The block number to start downloading from. Defaults to 0. + * @param from - The block number to start downloading from. Defaults to INITIAL_ROLLUP_ID. */ - public start(from = 0) { + public start(from = INITIAL_ROLLUP_ID) { this.from = from; if (this.running) { diff --git a/yarn-project/archiver/src/index.ts b/yarn-project/archiver/src/index.ts index 944dc8cb170a..30331f177d18 100644 --- a/yarn-project/archiver/src/index.ts +++ b/yarn-project/archiver/src/index.ts @@ -1,42 +1,54 @@ -// import { createPublicClient, getAddress, http } from 'viem'; -// import { localhost } from 'viem/chains'; -// import { Archiver } from './archiver/archiver.js'; +import { EthAddress } from '@aztec/ethereum.js/eth_address'; +import { fileURLToPath } from 'url'; +import { createPublicClient, getAddress, http } from 'viem'; +import { localhost } from 'viem/chains'; +import { Archiver } from './archiver/index.js'; export * from './archiver/index.js'; export * from './block_downloader/index.js'; export * from './l2_block/index.js'; -// const { -// ETHEREUM_HOST = 'http://localhost:8545/', -// ROLLUP_ADDRESS = '0x5FbDB2315678afecb367f032d93F642f64180aa3', -// YEETER_ADDRESS = '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512', -// } = process.env; - -// /** -// * A function which instantiates and starts Archiver. -// */ -// async function main() { -// const rollupAddress = getAddress(ROLLUP_ADDRESS); -// const yeeterAddress = getAddress(YEETER_ADDRESS); - -// const publicClient = createPublicClient({ -// chain: localhost, -// transport: http(ETHEREUM_HOST), -// }); - -// const archiver = new Archiver(publicClient, rollupAddress, yeeterAddress); - -// const shutdown = () => { -// archiver.stop(); -// process.exit(0); -// }; -// process.once('SIGINT', shutdown); -// process.once('SIGTERM', shutdown); - -// await archiver.start(); -// } - -// main().catch(err => { -// console.log(err); -// process.exit(1); -// }); +const { + ETHEREUM_HOST = 'http://localhost:8545/', + ROLLUP_ADDRESS = '0x5FbDB2315678afecb367f032d93F642f64180aa3', + YEETER_ADDRESS = '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512', +} = process.env; + +/** + * A function which instantiates and starts Archiver. + */ +// eslint-disable-next-line require-await +async function main() { + const rollupAddress = getAddress(ROLLUP_ADDRESS); + const yeeterAddress = getAddress(YEETER_ADDRESS); + + const publicClient = createPublicClient({ + chain: localhost, + transport: http(ETHEREUM_HOST), + }); + + const archiver = new Archiver( + publicClient, + EthAddress.fromString(rollupAddress), + EthAddress.fromString(yeeterAddress), + ); + + const shutdown = async () => { + await archiver.stop(); + process.exit(0); + }; + process.once('SIGINT', shutdown); + process.once('SIGTERM', shutdown); +} + +// See https://twitter.com/Rich_Harris/status/1355289863130673153 +if (process.argv[1] === fileURLToPath(import.meta.url).replace(/\/index\.js$/, '')) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + main().catch(err => { + console.log(err); + process.exit(1); + }); +} + +export { Archiver, mockRandomL2Block } from './archiver/index.js'; +export * from './l2_block/l2_block.js'; diff --git a/yarn-project/archiver/src/l2_block/index.ts b/yarn-project/archiver/src/l2_block/index.ts index e8e9e0a8a417..2cc58517e001 100644 --- a/yarn-project/archiver/src/l2_block/index.ts +++ b/yarn-project/archiver/src/l2_block/index.ts @@ -1,3 +1,2 @@ export * from './l2_block.js'; export * from './l2_block_source.js'; -export * from './mocks.js'; diff --git a/yarn-project/archiver/src/l2_block/l2_block.test.ts b/yarn-project/archiver/src/l2_block/l2_block.test.ts index 854498ae8f76..93c2318d236f 100644 --- a/yarn-project/archiver/src/l2_block/l2_block.test.ts +++ b/yarn-project/archiver/src/l2_block/l2_block.test.ts @@ -1,35 +1,13 @@ -import { randomBytes } from '@aztec/foundation'; -import { randomAppendOnlyTreeSnapshot, randomContractData } from './mocks.js'; -import { ContractData, L2Block } from './l2_block.js'; +import { mockRandomL2Block } from '../index.js'; +import { L2Block } from './l2_block.js'; describe('L2Block', () => { it('can encode a L2 block data object to buffer and back', () => { - const newNullifiers = [randomBytes(32), randomBytes(32), randomBytes(32), randomBytes(32)]; - const newCommitments = [randomBytes(32), randomBytes(32), randomBytes(32), randomBytes(32)]; - const newContracts: Buffer[] = [randomBytes(32)]; - const newContractsData: ContractData[] = [randomContractData()]; + const block = mockRandomL2Block(42); - const l2BlockData = new L2Block( - 0, - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(newCommitments.length), - randomAppendOnlyTreeSnapshot(newNullifiers.length), - randomAppendOnlyTreeSnapshot(newContracts.length), - randomAppendOnlyTreeSnapshot(1), - randomAppendOnlyTreeSnapshot(1), - newCommitments, - newNullifiers, - newContracts, - newContractsData, - ); - - const buffer = l2BlockData.encode(); + const buffer = block.encode(); const recovered = L2Block.decode(buffer); - expect(recovered).toEqual(l2BlockData); + expect(recovered).toEqual(block); }); }); diff --git a/yarn-project/archiver/src/l2_block/l2_block.ts b/yarn-project/archiver/src/l2_block/l2_block.ts index 8d5d4dd8eb4c..fd789ff83d59 100644 --- a/yarn-project/archiver/src/l2_block/l2_block.ts +++ b/yarn-project/archiver/src/l2_block/l2_block.ts @@ -1,35 +1,43 @@ -import { numToUInt32BE } from '@aztec/foundation'; - -/** - * A snapshot of an append only tree. - */ -export type AppendOnlyTreeSnapshot = { - /** - * The root of the tree, as a field element. - */ - root: Buffer; - /** - * The next available index in the tree. - */ - nextAvailableLeafIndex: number; -}; +import { AppendOnlyTreeSnapshot, EthAddress, Fr } from '@aztec/circuits.js'; +import { BufferReader, serializeToBuffer } from '@aztec/circuits.js/utils'; /** * A contract data blob, containing L1 and L2 addresses. */ -export type ContractData = { +export class ContractData { + constructor( + /** + * The L2 address of the contract, as a field element (32 bytes). + */ + public aztecAddress: Fr, + /** + * The L1 address of the contract, (20 bytes). + */ + public ethAddress: EthAddress, + ) {} + /** - * The L2 address of the contract, as a field element (32 bytes). + * Serializes this instance into a buffer, using 20 bytes for the eth address. + * @returns Encoded buffer. */ - aztecAddress: Buffer; + public toBuffer(): Buffer { + return serializeToBuffer(this.aztecAddress, this.ethAddress.buffer); + } + /** - * The L1 address of the contract, (20 bytes). + * Deserializes a contract data object from an encoded buffer, using 20 bytes for the eth address. + * @param buffer - Byte array resulting from calling toBuffer. + * @returns Deserialized instance. */ - ethAddress: Buffer; -}; + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new ContractData(reader.readFr(), new EthAddress(reader.readBytes(EthAddress.SIZE_IN_BYTES))); + } +} /** * The data that makes up the rollup proof, with encoder decoder functions. + * TODO: Reuse data types and serialization functions from circuits package. */ export class L2Block { /** @@ -68,12 +76,53 @@ export class L2Block { public endContractTreeSnapshot: AppendOnlyTreeSnapshot, public endTreeOfHistoricPrivateDataTreeRootsSnapshot: AppendOnlyTreeSnapshot, public endTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot, - public newCommitments: Buffer[], - public newNullifiers: Buffer[], - public newContracts: Buffer[], + public newCommitments: Fr[], + public newNullifiers: Fr[], + public newContracts: Fr[], public newContractData: ContractData[], ) {} + /** + * Constructs a new instance from named fields. + * @param fields - Fields to pass to the constructor. + * @returns A new instance. + */ + static fromFields(fields: { + number: number; + startPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot; + startNullifierTreeSnapshot: AppendOnlyTreeSnapshot; + startContractTreeSnapshot: AppendOnlyTreeSnapshot; + startTreeOfHistoricPrivateDataTreeRootsSnapshot: AppendOnlyTreeSnapshot; + startTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot; + endPrivateDataTreeSnapshot: AppendOnlyTreeSnapshot; + endNullifierTreeSnapshot: AppendOnlyTreeSnapshot; + endContractTreeSnapshot: AppendOnlyTreeSnapshot; + endTreeOfHistoricPrivateDataTreeRootsSnapshot: AppendOnlyTreeSnapshot; + endTreeOfHistoricContractTreeRootsSnapshot: AppendOnlyTreeSnapshot; + newCommitments: Fr[]; + newNullifiers: Fr[]; + newContracts: Fr[]; + newContractData: ContractData[]; + }) { + return new this( + fields.number, + fields.startPrivateDataTreeSnapshot, + fields.startNullifierTreeSnapshot, + fields.startContractTreeSnapshot, + fields.startTreeOfHistoricPrivateDataTreeRootsSnapshot, + fields.startTreeOfHistoricContractTreeRootsSnapshot, + fields.endPrivateDataTreeSnapshot, + fields.endNullifierTreeSnapshot, + fields.endContractTreeSnapshot, + fields.endTreeOfHistoricPrivateDataTreeRootsSnapshot, + fields.endTreeOfHistoricContractTreeRootsSnapshot, + fields.newCommitments, + fields.newNullifiers, + fields.newContracts, + fields.newContractData, + ); + } + /** * Sets the yeet on this block. * @param yeet - The yeet to set. @@ -87,26 +136,34 @@ export class L2Block { * @returns The encoded L2 block data. */ encode(): Buffer { - return Buffer.concat([ - numToUInt32BE(Number(this.number)), - appendOnlyTreeSnapshotToBuffer(this.startPrivateDataTreeSnapshot), - appendOnlyTreeSnapshotToBuffer(this.startNullifierTreeSnapshot), - appendOnlyTreeSnapshotToBuffer(this.startContractTreeSnapshot), - appendOnlyTreeSnapshotToBuffer(this.startTreeOfHistoricPrivateDataTreeRootsSnapshot), - appendOnlyTreeSnapshotToBuffer(this.startTreeOfHistoricContractTreeRootsSnapshot), - appendOnlyTreeSnapshotToBuffer(this.endPrivateDataTreeSnapshot), - appendOnlyTreeSnapshotToBuffer(this.endNullifierTreeSnapshot), - appendOnlyTreeSnapshotToBuffer(this.endContractTreeSnapshot), - appendOnlyTreeSnapshotToBuffer(this.endTreeOfHistoricPrivateDataTreeRootsSnapshot), - appendOnlyTreeSnapshotToBuffer(this.endTreeOfHistoricContractTreeRootsSnapshot), - numToUInt32BE(this.newCommitments.length), - ...this.newCommitments, - numToUInt32BE(this.newNullifiers.length), - ...this.newNullifiers, - numToUInt32BE(this.newContracts.length), - ...this.newContracts, - ...this.newContractData.map(contractData => contractDataToBuffer(contractData)), - ]); + return serializeToBuffer( + this.number, + this.startPrivateDataTreeSnapshot, + this.startNullifierTreeSnapshot, + this.startContractTreeSnapshot, + this.startTreeOfHistoricPrivateDataTreeRootsSnapshot, + this.startTreeOfHistoricContractTreeRootsSnapshot, + this.endPrivateDataTreeSnapshot, + this.endNullifierTreeSnapshot, + this.endContractTreeSnapshot, + this.endTreeOfHistoricPrivateDataTreeRootsSnapshot, + this.endTreeOfHistoricContractTreeRootsSnapshot, + this.newCommitments.length, + this.newCommitments, + this.newNullifiers.length, + this.newNullifiers, + this.newContracts.length, + this.newContracts, + this.newContractData, + ); + } + + /** + * Alias for encode. + * @returns The encoded L2 block data. + */ + toBuffer() { + return this.encode(); } /** @@ -114,70 +171,26 @@ export class L2Block { * @param encoded - The encoded L2 block data. * @returns The decoded L2 block data. */ - static decode(encoded: Buffer) { - let offset = 0; - const blockNum = encoded.readUInt32BE(offset); - offset += 4; - const startPrivateDataTreeSnapshot = bufferToAppendOnlyTreeSnapshot(encoded.subarray(offset, offset + 36)); - offset += 36; - const startNullifierTreeSnapshot = bufferToAppendOnlyTreeSnapshot(encoded.subarray(offset, offset + 36)); - offset += 36; - const startContractTreeSnapshot = bufferToAppendOnlyTreeSnapshot(encoded.subarray(offset, offset + 36)); - offset += 36; - const startTreeOfHistoricPrivateDataTreeRootsSnapshot = bufferToAppendOnlyTreeSnapshot( - encoded.subarray(offset, offset + 36), - ); - offset += 36; - const startTreeOfHistoricContractTreeRootsSnapshot = bufferToAppendOnlyTreeSnapshot( - encoded.subarray(offset, offset + 36), - ); - offset += 36; - const endPrivateDataTreeSnapshot = bufferToAppendOnlyTreeSnapshot(encoded.subarray(offset, offset + 36)); - offset += 36; - const endNullifierTreeSnapshot = bufferToAppendOnlyTreeSnapshot(encoded.subarray(offset, offset + 36)); - offset += 36; - const endContractTreeSnapshot = bufferToAppendOnlyTreeSnapshot(encoded.subarray(offset, offset + 36)); - offset += 36; - const endTreeOfHistoricPrivateDataTreeRootsSnapshot = bufferToAppendOnlyTreeSnapshot( - encoded.subarray(offset, offset + 36), - ); - offset += 36; - const endTreeOfHistoricContractTreeRootsSnapshot = bufferToAppendOnlyTreeSnapshot( - encoded.subarray(offset, offset + 36), - ); - offset += 36; - - const newCommitments: Buffer[] = []; - const newNullifiers: Buffer[] = []; - const newContracts: Buffer[] = []; - const newContractData: ContractData[] = []; - - const newCommitmentCount = encoded.readUInt32BE(offset); - offset += 4; - for (let i = 0; i < newCommitmentCount; i++) { - newCommitments.push(encoded.subarray(offset, offset + 32)); - offset += 32; - } - const newNullifierCount = encoded.readUInt32BE(offset); - offset += 4; - for (let i = 0; i < newNullifierCount; i++) { - newNullifiers.push(encoded.subarray(offset, offset + 32)); - offset += 32; - } - - const newContractCount = encoded.readUInt32BE(offset); - offset += 4; - for (let i = 0; i < newContractCount; i++) { - newContracts.push(encoded.subarray(offset, offset + 32)); - offset += 32; - } - for (let i = 0; i < newContractCount; i++) { - newContractData.push(bufferToContractData(encoded.subarray(offset, offset + 52))); - offset += 52; - } + static decode(encoded: Buffer | BufferReader) { + const reader = BufferReader.asReader(encoded); + const number = reader.readNumber(); + const startPrivateDataTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const startNullifierTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const startContractTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const startTreeOfHistoricPrivateDataTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const startTreeOfHistoricContractTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const endPrivateDataTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const endNullifierTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const endContractTreeSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const endTreeOfHistoricPrivateDataTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const endTreeOfHistoricContractTreeRootsSnapshot = reader.readObject(AppendOnlyTreeSnapshot); + const newCommitments = reader.readVector(Fr); + const newNullifiers = reader.readVector(Fr); + const newContracts = reader.readVector(Fr); + const newContractData = reader.readArray(newContracts.length, ContractData); return new L2Block( - blockNum, + number, startPrivateDataTreeSnapshot, startNullifierTreeSnapshot, startContractTreeSnapshot, @@ -194,55 +207,55 @@ export class L2Block { newContractData, ); } -} - -/** - * UTILITIES. - */ - -/** - * Serialize the contract data as a buffer. - * @param contractData - The contract data to serialize. - * @returns The serialized contract data as a buffer. - */ -export function contractDataToBuffer(contractData: ContractData): Buffer { - return Buffer.concat([contractData.aztecAddress, contractData.ethAddress]); -} -/** - * Deserialize the contract data from a buffer. - * @param buffer - The buffer to deserialize. - * @returns The contract data. - */ -export function bufferToContractData(buffer: Buffer): ContractData { - return { - aztecAddress: buffer.subarray(0, 32), - ethAddress: buffer.subarray(32, 52), - }; -} - -/** - * Serialize the append only tree snapshot as a buffer. - * @param snapshot - The snapshot to serialize. - * @returns The serialized snapshot as a buffer. - */ -export function appendOnlyTreeSnapshotToBuffer(snapshot: AppendOnlyTreeSnapshot): Buffer { - const buffer = Buffer.concat([numToUInt32BE(snapshot.nextAvailableLeafIndex), snapshot.root]); - return buffer; -} - -/** - * Deserialize the append only tree snapshot from a buffer. - * @param buffer - The buffer to deserialize. - * @returns The append only tree snapshot. - */ -export function bufferToAppendOnlyTreeSnapshot(buffer: Buffer): AppendOnlyTreeSnapshot { - const nextAvailableLeafIndex = buffer.readUInt32BE(0); - const root = buffer.subarray(4); - return { - nextAvailableLeafIndex, - root, - }; + /** + * Inspect for debugging purposes.. + * @param maxBufferSize - The number of bytes to be extracted from buffer. + * @returns A human-friendly string representation of the l2block. + */ + inspect(maxBufferSize = 4): string { + const inspectTreeSnapshot = (s: AppendOnlyTreeSnapshot): string => + `(${s.nextAvailableLeafIndex}, 0x${s.root.toBuffer().subarray(0, maxBufferSize).toString('hex')})`; + const inspectFrArray = (arr: Fr[]): string => + '[' + arr.map(fr => '0x' + fr.toBuffer().subarray(0, maxBufferSize).toString('hex')).join(', ') + ']'; + const inspectContractDataArray = (arr: ContractData[]): string => + '[' + + arr + .map( + cd => + `(0x${cd.aztecAddress.toBuffer().subarray(0, maxBufferSize).toString('hex')}, 0x${cd.ethAddress.buffer + .subarray(0, maxBufferSize) + .toString('hex')})`, + ) + .join(', ') + + ']'; + return [ + `L2Block`, + `number: ${this.number}`, + `startPrivateDataTreeSnapshot: ${inspectTreeSnapshot(this.startPrivateDataTreeSnapshot)}`, + `startNullifierTreeSnapshot: ${inspectTreeSnapshot(this.startNullifierTreeSnapshot)}`, + `startContractTreeSnapshot: ${inspectTreeSnapshot(this.startContractTreeSnapshot)}`, + `startTreeOfHistoricPrivateDataTreeRootsSnapshot: ${inspectTreeSnapshot( + this.startTreeOfHistoricPrivateDataTreeRootsSnapshot, + )}`, + `startTreeOfHistoricContractTreeRootsSnapshot: ${inspectTreeSnapshot( + this.startTreeOfHistoricContractTreeRootsSnapshot, + )}`, + `endPrivateDataTreeSnapshot: ${inspectTreeSnapshot(this.endPrivateDataTreeSnapshot)}`, + `endNullifierTreeSnapshot: ${inspectTreeSnapshot(this.endNullifierTreeSnapshot)}`, + `endContractTreeSnapshot: ${inspectTreeSnapshot(this.endContractTreeSnapshot)}`, + `endTreeOfHistoricPrivateDataTreeRootsSnapshot: ${inspectTreeSnapshot( + this.endTreeOfHistoricPrivateDataTreeRootsSnapshot, + )}`, + `endTreeOfHistoricContractTreeRootsSnapshot: ${inspectTreeSnapshot( + this.endTreeOfHistoricContractTreeRootsSnapshot, + )}`, + `newCommitments: ${inspectFrArray(this.newCommitments)}`, + `newNullifiers: ${inspectFrArray(this.newNullifiers)}`, + `newContracts: ${inspectFrArray(this.newContracts)}`, + `newContractData: ${inspectContractDataArray(this.newContractData)}`, + ].join('\n'); + } } /** diff --git a/yarn-project/archiver/src/l2_block/l2_block_source.ts b/yarn-project/archiver/src/l2_block/l2_block_source.ts index bb4d6e776950..620f9c21f77e 100644 --- a/yarn-project/archiver/src/l2_block/l2_block_source.ts +++ b/yarn-project/archiver/src/l2_block/l2_block_source.ts @@ -1,29 +1,9 @@ import { L2Block } from './index.js'; -/** - * Describes sync status of the archiver. - */ -export interface L2BlockSourceSyncStatus { - /** - * The height of the L2 block that the archiver is synced to. - */ - syncedToBlock: number; - /** - * Maximum height of a L2 block processed by the rollup contract. - */ - latestBlock: number; -} - /** * Interface of classes allowing for the retrieval of L2 blocks. */ export interface L2BlockSource { - /** - * Gets the sync status of the L2 block source. - * @returns The sync status of the L2 block source. - */ - getSyncStatus(): Promise; - /** * Gets the number of the latest L2 block processed by the block source implementation. * @returns The number of the latest L2 block processed by the block source implementation. diff --git a/yarn-project/archiver/src/l2_block/mocks.ts b/yarn-project/archiver/src/l2_block/mocks.ts deleted file mode 100644 index d7533c88a896..000000000000 --- a/yarn-project/archiver/src/l2_block/mocks.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { randomBytes } from '@aztec/foundation'; - -import { AppendOnlyTreeSnapshot, ContractData } from './l2_block.js'; - -export const randomAppendOnlyTreeSnapshot = (nextIndex: number): AppendOnlyTreeSnapshot => { - return { - root: randomBytes(32), - nextAvailableLeafIndex: nextIndex, - }; -}; - -export const randomContractData = (): ContractData => { - return { - aztecAddress: randomBytes(32), - ethAddress: randomBytes(20), - }; -}; diff --git a/yarn-project/archiver/test/archiver-integration.test.ts b/yarn-project/archiver/test/archiver-integration.test.ts new file mode 100644 index 000000000000..59051ac40a7d --- /dev/null +++ b/yarn-project/archiver/test/archiver-integration.test.ts @@ -0,0 +1,67 @@ +import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc'; +import { WalletProvider } from '@aztec/ethereum.js/provider'; +import { Rollup, Yeeter } from '@aztec/l1-contracts'; +import { beforeAll, describe, expect, it } from '@jest/globals'; +import { createPublicClient, hexToBytes, http } from 'viem'; +import { localhost } from 'viem/chains'; +import { Archiver, INITIAL_BLOCK_NUM, L2Block, mockRandomL2Block } from '../src/index.js'; + +// Accounts 4 and 5 of Anvil default startup with mnemonic: 'test test test test test test test test test test test junk' +const sequencerPK = '0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a'; +const deployerPK = '0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba'; +const anvilHost = process.env.ANVIL_HOST ?? 'http://127.0.0.1:8545'; + +describe('Archiver integration', () => { + let rollup: Rollup; + let yeeter: Yeeter; + let l2Block: L2Block; + let l2Proof: Buffer; + let archiver: Archiver; + + beforeAll(async () => { + ({ rollup, yeeter } = await deployContracts()); + + l2Block = mockRandomL2Block(INITIAL_BLOCK_NUM); + l2Proof = Buffer.alloc(0); + + const publicClient = createPublicClient({ + chain: localhost, + transport: http(anvilHost), + }); + + archiver = new Archiver(publicClient, rollup.address, yeeter.address); + }); + + it('reads l2block from archiver initial sync', async () => { + await rollup.methods.process(l2Proof, l2Block.encode()).send({ gas: 3e6 }).getReceipt(true, 0); + + await archiver.start(); + const blocks = await archiver.getL2Blocks(0, 1); + await archiver.stop(); + + expect(blocks).toHaveLength(1); + expect(blocks[0]).toEqual(l2Block); + }); +}); + +async function deployContracts() { + // Set up client + const provider = WalletProvider.fromHost(anvilHost); + provider.addAccount(Buffer.from(hexToBytes(deployerPK))); + provider.addAccount(Buffer.from(hexToBytes(sequencerPK))); + const [sequencer, deployer] = provider.getAccounts(); + const ethRpc = new EthereumRpc(provider); + + // Deploy contracts + const deployedRollup = new Rollup(ethRpc, undefined, { from: deployer, gas: 1e6 }); + await deployedRollup.deploy().send().getReceipt(); + + const deployedYeeter = new Yeeter(ethRpc, undefined, { from: deployer, gas: 1e6 }); + await deployedYeeter.deploy().send().getReceipt(); + + // Create new instance so we can attach the sequencer as sender + const rollup = new Rollup(ethRpc, deployedRollup.address, { from: sequencer }); + const yeeter = new Yeeter(ethRpc, deployedYeeter.address, { from: sequencer }); + + return { rollup, yeeter, deployer, sequencer, ethRpc }; +} \ No newline at end of file diff --git a/yarn-project/archiver/tsconfig.dest.json b/yarn-project/archiver/tsconfig.dest.json index 424bb413ffbc..74b01e790de4 100644 --- a/yarn-project/archiver/tsconfig.dest.json +++ b/yarn-project/archiver/tsconfig.dest.json @@ -1,12 +1,18 @@ { "extends": ".", + "exclude": ["**/*.test.*", "**/fixtures/*"], "references": [ { "path": "../ethereum.js/tsconfig.dest.json" }, { "path": "../foundation/tsconfig.dest.json" + }, + { + "path": "../circuits.js/tsconfig.dest.json" + }, + { + "path": "../l1-contracts/tsconfig.dest.json" } - ], - "exclude": ["**/*.test.*", "**/fixtures/*"] + ] } diff --git a/yarn-project/archiver/tsconfig.json b/yarn-project/archiver/tsconfig.json index afaa5db00cb7..b915eebf6c65 100644 --- a/yarn-project/archiver/tsconfig.json +++ b/yarn-project/archiver/tsconfig.json @@ -6,11 +6,18 @@ "tsBuildInfoFile": ".tsbuildinfo" }, "references": [ + { + "path": "../ethereum.js/tsconfig.dest.json" + }, { "path": "../foundation/tsconfig.dest.json" + }, + { + "path": "../circuits.js/tsconfig.dest.json" + }, + { + "path": "../l1-contracts/tsconfig.dest.json" } ], - "include": [ - "src" - ] -} \ No newline at end of file + "include": ["src", "test"] +} diff --git a/yarn-project/aztec-node/jest.integration.config.json b/yarn-project/aztec-node/jest.integration.config.json new file mode 100644 index 000000000000..f89093c1acff --- /dev/null +++ b/yarn-project/aztec-node/jest.integration.config.json @@ -0,0 +1,13 @@ +{ + "preset": "ts-jest/presets/default-esm", + "globals": { + "ts-jest": { + "useESM": true + } + }, + "moduleNameMapper": { + "^(\\.{1,2}/.*)\\.js$": "$1" + }, + "testRegex": "./test/.*\\.test\\.ts$", + "rootDir": "./test" +} \ No newline at end of file diff --git a/yarn-project/aztec-node/package.json b/yarn-project/aztec-node/package.json index af38735290d3..11be37960c10 100644 --- a/yarn-project/aztec-node/package.json +++ b/yarn-project/aztec-node/package.json @@ -14,7 +14,10 @@ "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", - "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" + "formatting:fix": "run -T prettier -w ./src", + "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests", + "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"", + "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json" }, "jest": { "preset": "ts-jest/presets/default-esm", @@ -32,7 +35,10 @@ "dependencies": { "@aztec/archiver": "workspace:^", "@aztec/ethereum.js": "workspace:^", + "@aztec/foundation": "workspace:^", + "@aztec/l1-contracts": "workspace:^", "@aztec/p2p": "workspace:^", + "@aztec/sequencer-client": "workspace:^", "@aztec/world-state": "workspace:^", "tslib": "^2.4.0" }, @@ -41,6 +47,7 @@ "@rushstack/eslint-patch": "^1.1.4", "@types/jest": "^29.4.0", "@types/node": "^18.7.23", + "concurrently": "^7.6.0", "jest": "^28.1.3", "ts-jest": "^28.0.7", "ts-node": "^10.9.1", diff --git a/yarn-project/aztec-node/src/aztec-node/aztec-node.ts b/yarn-project/aztec-node/src/aztec-node/aztec-node.ts new file mode 100644 index 000000000000..6aa50bb9ce84 --- /dev/null +++ b/yarn-project/aztec-node/src/aztec-node/aztec-node.ts @@ -0,0 +1,111 @@ +import { default as levelup } from 'levelup'; +import { default as memdown } from 'memdown'; +import { L2BlockSource, Archiver } from '@aztec/archiver'; +import { P2P, P2PClient, Tx } from '@aztec/p2p'; +import { MerkleTrees, WorldStateSynchroniser, ServerWorldStateSynchroniser } from '@aztec/world-state'; +import { SequencerClient } from '@aztec/sequencer-client'; +import { AztecNodeConfig } from './config.js'; + +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// @ts-ignore +export const createMemDown = () => memdown(); + +/** + * The aztec node. + */ +export class AztecNode { + constructor( + private p2pClient?: P2P, + private blockSource?: L2BlockSource, + private merkleTreeDB?: MerkleTrees, + private worldStateSynchroniser?: WorldStateSynchroniser, + private sequencer?: SequencerClient, + ) {} + + /** + * Initialises the Aztec Node, wait for component to sync. + * @param config - The configuration to be used by the aztec node. + * @returns - A fully synced Aztec Node for use in development/testing. + */ + public static async createAndSync(config: AztecNodeConfig) { + // first create and sync the archiver + const blockSource = await Archiver.createAndSync(config); + + // give the block source to the P2P network + const p2pClient = new P2PClient(blockSource); + + // now create the merkle trees and the world state syncher + const merkleTreeDB = await MerkleTrees.new(levelup(createMemDown())); + const worldStateSynchroniser = new ServerWorldStateSynchroniser(merkleTreeDB, blockSource); + + // start both and wait for them to sync from the block source + await Promise.all([p2pClient.start(), worldStateSynchroniser.start()]); + + // now create the sequencer + const sequencer = await SequencerClient.new(config, p2pClient, worldStateSynchroniser); + return new AztecNode(p2pClient, blockSource, merkleTreeDB, worldStateSynchroniser, sequencer); + } + + /** + * Method to determine if the node is ready to accept transactions. + * @returns - Flag indicating the readiness for tx submission. + */ + public async isReady() { + return (await this.p2pClient?.isReady()) ?? false; + } + + /** + * Method to request blocks. Will attempt to return all requested blocks but will return only those available. + * @param from - The start of the range of blocks to return. + * @param take - The number of blocks desired. + * @returns The blocks requested. + */ + public async getBlocks(from: number, take: number) { + this.verifyInitialised(); + return (await this.blockSource?.getL2Blocks(from, take)) ?? []; + } + + /** + * Method to submit a transaction to the p2p pool. + * @param tx - The transaction to be submitted. + */ + public async sendTx(tx: Tx) { + this.verifyInitialised(); + await this.p2pClient!.sendTx(tx); + } + + /** + * Method to stop the aztec node. + */ + public async stop() { + await this.p2pClient?.stop(); + await this.worldStateSynchroniser?.stop(); + await this.merkleTreeDB?.stop(); + await this.sequencer?.stop(); + await this.blockSource?.stop(); + } + + /** + * Method to retrieve pending txs. + * @returns - The pending txs. + */ + public async getTxs() { + return await this.p2pClient!.getTxs(); + } + + /** + * Method to verify that we are initialised, throws if not. + */ + private verifyInitialised() { + const invalid = [ + this.blockSource, + this.merkleTreeDB, + this.p2pClient, + this.worldStateSynchroniser, + this.sequencer, + ].findIndex(x => !x); + if (invalid != -1) { + throw new Error('Aztec Node not initialised'); + } + } +} diff --git a/yarn-project/aztec-node/src/aztec-node/aztec_node.test.ts b/yarn-project/aztec-node/src/aztec-node/aztec_node.test.ts new file mode 100644 index 000000000000..5da0b374f832 --- /dev/null +++ b/yarn-project/aztec-node/src/aztec-node/aztec_node.test.ts @@ -0,0 +1,90 @@ +import { EthAddress } from '@aztec/ethereum.js/eth_address'; +import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc'; +import { WalletProvider } from '@aztec/ethereum.js/provider'; +import { Tx } from '@aztec/p2p'; +import { AztecNodeConfig } from './config.js'; +import { AztecNode } from '../index.js'; +import { createProvider, createTx, deployRollupContract, deployYeeterContract } from './fixtures.js'; +import { createDebugLogger, sleep } from '@aztec/foundation'; + +const ETHEREUM_HOST = 'http://localhost:8545/'; +const MNEMONIC = 'test test test test test test test test test test test junk'; + +const logger = createDebugLogger('aztec:e2e_test'); + +describe('AztecNode', () => { + let rollupAddress: EthAddress; + let yeeterAddress: EthAddress; + let node: AztecNode; + let isReady: boolean; + let provider: WalletProvider; + + beforeEach(async () => { + provider = createProvider(ETHEREUM_HOST, MNEMONIC, 1); + const ethRpc = new EthereumRpc(provider); + rollupAddress = await deployRollupContract(provider, ethRpc); + yeeterAddress = await deployYeeterContract(provider, ethRpc); + + const aztecNodeConfig = { + rollupContract: rollupAddress, + yeeterContract: yeeterAddress, + rpcUrl: ETHEREUM_HOST, + publisherPrivateKey: provider.getPrivateKey(0), + archiverPollingInterval: 100, + } as AztecNodeConfig; + + node = await AztecNode.createAndSync(aztecNodeConfig); + isReady = await node.isReady(); + }); + + it('should start and stop all services', async () => { + expect(isReady).toBeTruthy(); + await node.stop(); + }); + + it('should rollup a transaction', async () => { + const tx: Tx = createTx(); + await node.sendTx(tx); + + const [settledBlock] = await waitForBlocks(1); + + expect(settledBlock.number).toBe(1); + expect(settledBlock.newContracts.length).toBeGreaterThan(0); + expect(settledBlock.newContracts[0]).toEqual(tx.data.end.newContracts[0].functionTreeRoot); + + await node.stop(); + }, 30_000); + + it('should rollup multiple transactions', async () => { + const txs: Tx[] = Array(3).fill(0).map(createTx); + for (let i = 0; i < txs.length; i++) { + logger(`Sending tx ${i + 1} of ${txs.length}`); + await node.sendTx(txs[i]); + } + const blocks = await waitForBlocks(3); + + logger(`Received ${blocks.length} settled blocks`); + + for (let i = 0; i < 3; i++) { + const tx = txs[i]; + const block = blocks[i]; + expect(block.number).toBe(i + 1); + expect(block.newContracts.length).toBeGreaterThan(0); + expect(block.newContracts[0]).toEqual(tx.data.end.newContracts[0].functionTreeRoot); + logger(`Verified tx ${i + 1}`); + } + + await node.stop(); + }, 30_000 /* timeout in ms */); + + const waitForBlocks = async (take: number) => { + while (true) { + const blocks = await node.getBlocks(1, take); + if (blocks.length < take) { + await sleep(100); + continue; + } + return blocks; + } + }; +}); diff --git a/yarn-project/aztec-node/src/aztec-node/config.ts b/yarn-project/aztec-node/src/aztec-node/config.ts new file mode 100644 index 000000000000..d349adc3c1d4 --- /dev/null +++ b/yarn-project/aztec-node/src/aztec-node/config.ts @@ -0,0 +1,7 @@ +import { ArchiverConfig } from '@aztec/archiver'; +import { SequencerClientConfig } from '@aztec/sequencer-client'; + +/** + * The configuration the aztec node. + */ +export type AztecNodeConfig = ArchiverConfig & SequencerClientConfig; diff --git a/yarn-project/aztec-node/src/aztec-node/fixtures.ts b/yarn-project/aztec-node/src/aztec-node/fixtures.ts new file mode 100644 index 000000000000..aa89512c8541 --- /dev/null +++ b/yarn-project/aztec-node/src/aztec-node/fixtures.ts @@ -0,0 +1,124 @@ +import { + AccumulatedData, + AffineElement, + AggregationObject, + ConstantData, + ContractDeploymentData, + EMITTED_EVENTS_LENGTH, + EthAddress as CircuitEthAddress, + Fq, + Fr, + FunctionData, + KERNEL_L1_MSG_STACK_LENGTH, + KERNEL_NEW_COMMITMENTS_LENGTH, + KERNEL_NEW_CONTRACTS_LENGTH, + KERNEL_NEW_NULLIFIERS_LENGTH, + KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH, + KERNEL_PRIVATE_CALL_STACK_LENGTH, + KERNEL_PUBLIC_CALL_STACK_LENGTH, + NewContractData, + OldTreeRoots, + OptionallyRevealedData, + PrivateKernelPublicInputs, + TxContext, +} from '@aztec/circuits.js'; +import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc'; +import { WalletProvider } from '@aztec/ethereum.js/provider'; +import { randomBytes } from '@aztec/foundation'; +import { Rollup, Yeeter } from '@aztec/l1-contracts'; +import { Tx } from '@aztec/p2p'; + +// REFACTOR: Move deployment logic to l1-contracts package, and refactor it out of other integration tests (archiver, sequencer) +export const deployRollupContract = async (provider: WalletProvider, ethRpc: EthereumRpc) => { + const deployAccount = provider.getAccount(0); + const contract = new Rollup(ethRpc, undefined, { from: deployAccount, gas: 1000000 }); + await contract.deploy().send().getReceipt(); + return contract.address; +}; + +export const deployYeeterContract = async (provider: WalletProvider, ethRpc: EthereumRpc) => { + const deployAccount = provider.getAccount(0); + const contract = new Yeeter(ethRpc, undefined, { from: deployAccount, gas: 1000000 }); + await contract.deploy().send().getReceipt(); + return contract.address; +}; + +export const createProvider = (host: string, mnemonic: string, accounts: number) => { + const walletProvider = WalletProvider.fromHost(host); + walletProvider.addAccountsFromMnemonic(mnemonic, accounts); + return walletProvider; +}; + +// REFACTOR: Use @aztec/circuit.js/factories where possible +export const createCircuitEthAddress = () => { + return new CircuitEthAddress(randomBytes(20)); +}; + +export const createRandomCommitments = (num: number) => { + return Array(num) + .fill(0) + .map(() => new Fr(randomBytes(32))); +}; + +export const createOptionallyRetrievedData = () => { + const func = new FunctionData(0, true, true); + return new OptionallyRevealedData( + new Fr(0), + func, + createRandomCommitments(EMITTED_EVENTS_LENGTH), + new Fr(0), + createCircuitEthAddress(), + true, + true, + true, + true, + ); +}; + +export const createOptionallyRetrievedDatas = (num: number) => { + return Array(num) + .fill(0) + .map(() => createOptionallyRetrievedData()); +}; + +export const createNewContractData = () => { + return new NewContractData(new Fr(randomBytes(32)), createCircuitEthAddress(), new Fr(randomBytes(32))); +}; + +export const createNewContractDatas = (num: number) => { + return Array(num) + .fill(0) + .map(() => createNewContractData()); +}; + +export const createTx = () => { + const oldTreeRoots = new OldTreeRoots(new Fr(0), new Fr(0), new Fr(0), new Fr(0)); + const contractDeploymentData = new ContractDeploymentData( + new Fr(randomBytes(32)), + new Fr(randomBytes(32)), + new Fr(randomBytes(32)), + createCircuitEthAddress(), + ); + const txContext = new TxContext(false, false, true, contractDeploymentData); + const constantData = new ConstantData(oldTreeRoots, txContext); + const aggregationObject = new AggregationObject( + new AffineElement(new Fq(0), new Fq(0)), + new AffineElement(new Fq(0), new Fq(0)), + [], + [], + false, + ); + const accumulatedData = new AccumulatedData( + aggregationObject, + new Fr(0), + createRandomCommitments(KERNEL_NEW_COMMITMENTS_LENGTH), + createRandomCommitments(KERNEL_NEW_NULLIFIERS_LENGTH), + createRandomCommitments(KERNEL_PRIVATE_CALL_STACK_LENGTH), + createRandomCommitments(KERNEL_PUBLIC_CALL_STACK_LENGTH), + createRandomCommitments(KERNEL_L1_MSG_STACK_LENGTH), + createNewContractDatas(KERNEL_NEW_CONTRACTS_LENGTH), + createOptionallyRetrievedDatas(KERNEL_OPTIONALLY_REVEALED_DATA_LENGTH), + ); + const kernelInputs = new PrivateKernelPublicInputs(accumulatedData, constantData, true); + return new Tx(kernelInputs); +}; diff --git a/yarn-project/aztec-node/src/aztec_node.test.ts b/yarn-project/aztec-node/src/aztec_node.test.ts deleted file mode 100644 index ba2fc950e085..000000000000 --- a/yarn-project/aztec-node/src/aztec_node.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { EthAddress } from '@aztec/ethereum.js/eth_address'; -import { AccumulatedTxData, Tx } from '@aztec/p2p'; -import { AztecNode } from './index.js'; - -const ETHEREUM_HOST = 'http://localhost:8545/'; -const ROLLUP_ADDRESS = '0x5FbDB2315678afecb367f032d93F642f64180aa3'; -const YEETER_ADDRESS = '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512'; - -describe('AztecNode', () => { - it('should start and stop all services', async () => { - const node = new AztecNode(); - await node.init(ETHEREUM_HOST, EthAddress.fromString(ROLLUP_ADDRESS), EthAddress.fromString(YEETER_ADDRESS)); - const isReady = await node.isReady(); - expect(isReady).toBeTruthy(); - await node.stop(); - }); - - it('should accept a transaction', async () => { - const node = new AztecNode(); - await node.init(ETHEREUM_HOST, EthAddress.fromString(ROLLUP_ADDRESS), EthAddress.fromString(YEETER_ADDRESS)); - const isReady = await node.isReady(); - expect(isReady).toBeTruthy(); - const tx: Tx = new Tx(AccumulatedTxData.random()); - await node.sendTx(tx); - const txs = await node.getTxs(); - expect(txs.length).toBe(1); - expect(txs[0].txId).toEqual(tx.txId); - }); -}); diff --git a/yarn-project/aztec-node/src/index.ts b/yarn-project/aztec-node/src/index.ts index 2e9253bb3939..c88603236fb6 100644 --- a/yarn-project/aztec-node/src/index.ts +++ b/yarn-project/aztec-node/src/index.ts @@ -1,109 +1,2 @@ -import { default as levelup } from 'levelup'; -import { default as memdown } from 'memdown'; -import { L2BlockSource, Archiver } from '@aztec/archiver'; -import { P2P, P2PCLient } from '@aztec/p2p'; -import { MerkleTrees, WorldStateSynchroniser, ServerWorldStateSynchroniser } from '@aztec/world-state'; -import { EthAddress } from '@aztec/ethereum.js/eth_address'; -import { Tx } from '@aztec/p2p'; - -export { Tx } from '@aztec/p2p'; - -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-ignore -export const createMemDown = () => memdown(); - -/** - * The public client. - */ -export class AztecNode { - private p2pClient?: P2P; - private blockSource?: L2BlockSource; - private merkleTreeDB?: MerkleTrees; - private worldStateSynchroniser?: WorldStateSynchroniser; - - constructor() {} - - /** - * Initialises the Aztec Node, wait for component to sync. - * @param rpcUrl - The URL of an Ethereum RPC node. - * @param rollupAddress - The rollup contract address. - * @param yeeterAddress - The yeeter contract address. - */ - public async init(rpcUrl: string, rollupAddress: EthAddress, yeeterAddress: EthAddress) { - // first configure the block source - this.blockSource = Archiver.new(rpcUrl, rollupAddress, yeeterAddress); - - await this.blockSource.start(); - - // give the block source to the P2P network and the world state synchroniser - this.p2pClient = new P2PCLient(this.blockSource); - const db = levelup(createMemDown()); - this.merkleTreeDB = await MerkleTrees.new(db); - this.worldStateSynchroniser = new ServerWorldStateSynchroniser(this.merkleTreeDB, this.blockSource); - - // start both and wait for them to sync from the block source - const p2pSyncPromise = this.p2pClient.start(); - const worldStateSyncPromise = this.worldStateSynchroniser.start(); - await Promise.all([p2pSyncPromise, worldStateSyncPromise]); - - // create and start the sequencer - // new Sequencer(this.blockSource, this.p2pClient, this.merkleTreeDB, this.publisher); - } - - /** - * Method to determine if the node is ready to accept transactions. - * @returns - Flag indicating the readiness for tx submission. - */ - public async isReady() { - return (await this.p2pClient?.isReady()) ?? false; - } - - /** - * Method to request blocks. Will attempt to return all requested blocks but will return only those available. - * @param from - The start of the range of blocks to return. - * @param take - The number of blocks desired. - * @returns The blocks requested. - */ - public async getBlocks(from: number, take: number) { - this.verifyInitialised(); - return (await this.blockSource?.getL2Blocks(from, take)) ?? []; - } - - /** - * Method to submit a transaction to the p2p pool. - * @param tx - The transaction to be submitted. - */ - public async sendTx(tx: Tx) { - this.verifyInitialised(); - await this.p2pClient!.sendTx(tx); - } - - /** - * Method to stop the aztec node. - */ - public async stop() { - this.verifyInitialised(); - await this.p2pClient!.stop(); - await this.worldStateSynchroniser!.stop(); - await this.merkleTreeDB!.stop(); - await this.blockSource!.stop(); - } - - /** - * Method to retrieve pending txs. - * @returns - The pending txs. - */ - public async getTxs() { - return await this.p2pClient!.getTxs(); - } - - /** - * Method to verify that we are initialised, throws if not. - */ - private verifyInitialised() { - const invalid = [this.blockSource, this.merkleTreeDB, this.p2pClient, this.worldStateSynchroniser].filter(x => !x); - if (invalid.length) { - throw new Error('Aztec Node not initialised'); - } - } -} +export * from './aztec-node/aztec-node.js'; +export * from './aztec-node/config.js'; diff --git a/yarn-project/aztec-node/tsconfig.dest.json b/yarn-project/aztec-node/tsconfig.dest.json index 1c9a9e1edac8..512ed2646c13 100644 --- a/yarn-project/aztec-node/tsconfig.dest.json +++ b/yarn-project/aztec-node/tsconfig.dest.json @@ -12,6 +12,15 @@ }, { "path": "../world-state/tsconfig.dest.json" + }, + { + "path": "../ethereum.js/tsconfig.dest.json" + }, + { + "path": "../l1-contracts/tsconfig.dest.json" + }, + { + "path": "../sequencer-client/tsconfig.dest.json" } ], "exclude": ["**/*.test.*", "**/fixtures/*"] diff --git a/yarn-project/aztec-node/tsconfig.json b/yarn-project/aztec-node/tsconfig.json index f67ddec9fd6b..a9095b7ad351 100644 --- a/yarn-project/aztec-node/tsconfig.json +++ b/yarn-project/aztec-node/tsconfig.json @@ -5,5 +5,28 @@ "rootDir": "src", "tsBuildInfoFile": ".tsbuildinfo" }, - "include": ["src"] + "references": [ + { + "path": "../archiver/tsconfig.dest.json" + }, + { + "path": "../foundation/tsconfig.dest.json" + }, + { + "path": "../p2p/tsconfig.dest.json" + }, + { + "path": "../world-state/tsconfig.dest.json" + }, + { + "path": "../ethereum.js/tsconfig.dest.json" + }, + { + "path": "../l1-contracts/tsconfig.dest.json" + }, + { + "path": "../sequencer-client/tsconfig.dest.json" + } + ], + "include": ["src", "test"] } diff --git a/yarn-project/circuits.js b/yarn-project/circuits.js new file mode 120000 index 000000000000..bb2712f45814 --- /dev/null +++ b/yarn-project/circuits.js @@ -0,0 +1 @@ +../circuits/ts \ No newline at end of file diff --git a/yarn-project/l1-contracts/contracts.json b/yarn-project/l1-contracts/contracts.json index dc961d2a737c..e482463d88b4 100644 --- a/yarn-project/l1-contracts/contracts.json +++ b/yarn-project/l1-contracts/contracts.json @@ -1,9 +1,13 @@ { - "outputPath": "./src/aztec-ethereumjs-contracts", + "outputPath": "./src/ethereumjs-contracts", "contracts": { "Rollup": { "source": "foundry", "buildFile": "../../l1-contracts/out/Rollup.sol/Rollup.json" + }, + "Yeeter": { + "source": "foundry", + "buildFile": "../../l1-contracts/out/Yeeter.sol/Yeeter.json" } } } \ No newline at end of file diff --git a/yarn-project/l1-contracts/package.json b/yarn-project/l1-contracts/package.json index e3242ac058da..3e1256111195 100644 --- a/yarn-project/l1-contracts/package.json +++ b/yarn-project/l1-contracts/package.json @@ -2,7 +2,10 @@ "name": "@aztec/l1-contracts", "version": "0.0.0", "type": "module", - "exports": "./dest/index.js", + "exports": { + ".": "./dest/index.js", + "./viem": "./dest/viem-abis/index.js" + }, "typedoc": { "entryPoint": "./src/index.ts", "displayName": "L1 Contracts", @@ -11,9 +14,10 @@ "scripts": { "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", - "generate": "contract_gen_def", + "generate": "contract_gen_def && bash scripts/update-viem-abis.sh && yarn formatting:fix", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", + "formatting:fix": "run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" }, "jest": { diff --git a/yarn-project/l1-contracts/scripts/update-viem-abis.sh b/yarn-project/l1-contracts/scripts/update-viem-abis.sh new file mode 100755 index 000000000000..41ba1906116d --- /dev/null +++ b/yarn-project/l1-contracts/scripts/update-viem-abis.sh @@ -0,0 +1,9 @@ +set -euo pipefail; + +echo -ne "/**\n * Rollup ABI for viem.\n */\nexport const RollupAbi = " > ./src/viem-abis/RollupAbi.ts; +jq -j '.abi' ../../l1-contracts/out/Rollup.sol/Rollup.json >> ./src/viem-abis/RollupAbi.ts; +echo " as const;" >> ./src/viem-abis/RollupAbi.ts; + +echo -ne "/**\n * Yeeter ABI for viem.\n */\nexport const YeeterAbi = " > ./src/viem-abis/YeeterAbi.ts; +jq -j '.abi' ../../l1-contracts/out/Yeeter.sol/Yeeter.json >> ./src/viem-abis/YeeterAbi.ts; +echo " as const;" >> ./src/viem-abis/YeeterAbi.ts; diff --git a/yarn-project/l1-contracts/src/aztec-ethereumjs-contracts/Rollup.ts b/yarn-project/l1-contracts/src/aztec-ethereumjs-contracts/Rollup.ts deleted file mode 100644 index 3f72c762e855..000000000000 --- a/yarn-project/l1-contracts/src/aztec-ethereumjs-contracts/Rollup.ts +++ /dev/null @@ -1,42 +0,0 @@ -// THIS IS GENERATED CODE, DO NOT EDIT! -/* eslint-disable */ -import { EthAddress } from '@aztec/ethereum.js/eth_address'; -import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc'; -import { Contract, ContractTxReceipt, EventLog, Options, TxCall, TxSend } from '@aztec/ethereum.js/contract'; -import * as Bytes from '@aztec/ethereum.js/contract/bytes.js'; -import abi from './RollupAbi.js'; -export type RollupBlockProcessedEvent = { - rollupBlockNumber: bigint; -}; -export interface RollupBlockProcessedEventLog extends EventLog {} -interface RollupEvents { - RollupBlockProcessed: RollupBlockProcessedEvent; -} -interface RollupEventLogs { - RollupBlockProcessed: RollupBlockProcessedEventLog; -} -interface RollupTxEventLogs { - RollupBlockProcessed: RollupBlockProcessedEventLog[]; -} -export interface RollupTransactionReceipt extends ContractTxReceipt {} -interface RollupMethods { - processRollup(_proof: Bytes.Bytes, _inputs: Bytes.Bytes): TxSend; - rollupStateHash(): TxCall; - verifier(): TxCall; -} -export interface RollupDefinition { - methods: RollupMethods; - events: RollupEvents; - eventLogs: RollupEventLogs; -} -export class Rollup extends Contract { - constructor(eth: EthereumRpc, address?: EthAddress, options?: Options) { - super(eth, abi, address, options); - } - deploy(): TxSend { - return super.deployBytecode( - '0x60a060405234801561001057600080fd5b5060405161001d9061004b565b604051809103906000f080158015610039573d6000803e3d6000fd5b506001600160a01b0316608052610058565b61019d80610e8883390190565b608051610e0f610079600039600081816067015261016a0152610e0f6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80631ab9c603146100465780632b7ac3f314610062578063f81cccbe146100a1575b600080fd5b61004f60005481565b6040519081526020015b60405180910390f35b6100897f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610059565b6100b46100af366004610adf565b6100b6565b005b6000806000806100c585610235565b60005493975091955093509150158015906100e257508260005414155b1561011257600054604051632d2ef59f60e11b815260048101919091526024810184905260440160405180910390fd5b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061014857610148610b43565b6020908102919091010152604051633a94343960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ea50d0e4906101a1908a908590600401610b7d565b602060405180830381865afa1580156101be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e29190610bf7565b6101ff576040516309bde33960e01b815260040160405180910390fd5b600083815560405186917f3b8a2090d4235f22cdb27dec2d75d724354dd3c747beb2df2bd09f1f251428b391a250505050505050565b600080600080610249856020015160e01c90565b9350610261610259600186610c36565b600487610283565b925061026f8460b887610283565b915061027a85610335565b90509193509193565b6040805160b880825260e082019092526000918291906020820181803683370190505090508460181c60208201538460101c60218201538460081c602282015384602382015360b46024820160b486602001860160045afa506002816040516102ec9190610c4f565b602060405180830381855afa158015610309573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061032c9190610c6b565b95945050505050565b60008060006103468461016c61049a565b909250905060008061036e8661035d866020610c84565b61036990610170610c9b565b61049a565b90925090506000806103a0886103848689610c9b565b61038f906020610c84565b61039b90610174610c9b565b61060d565b909250905060006103dd89846103b6888b610c9b565b6103c09190610c9b565b6103cb906020610c84565b6103d790610174610c9b565b8561076e565b604080516101ec8082526102208201909252919250906000908260208201818036833701905050905081602082018360208e0160045afa5061018c81018690526101ac81018890526101cc81018490526101ec810183905260405161020c9060029061044a908490610c4f565b602060405180830381855afa158015610467573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061048a9190610c6b565b9c9b505050505050505050505050565b8181016020015160e01c60006008816104b38285610cae565b67ffffffffffffffff8111156104cb576104cb610a3c565b6040519080825280602002602001820160405280156104f4578160200160208202803683370190505b50905060005b6105048386610cae565b8110156105f5576000610518826008610c84565b610523906020610c84565b61052e886024610c9b565b6105389190610c9b565b6040805161010080825261012082019092529192506000919060208201818036833701905050905061010060208201610100848c0160045afa506002816040516105829190610c4f565b602060405180830381855afa15801561059f573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105c29190610c6b565b8484815181106105d4576105d4610b43565b602002602001018181525050505080806105ed90610cd0565b9150506104fa565b506000610601826108c4565b93505050509250929050565b8181016020015160e01c60006002816106268285610cae565b67ffffffffffffffff81111561063e5761063e610a3c565b604051908082528060200260200182016040528015610667578160200160208202803683370190505b50905060005b6106778386610cae565b81101561075657600061068b826040610c84565b610696886024610c9b565b6106a09190610c9b565b60408051818152606081018252919250600091906020820181803683370190505090506040602082016040848c0160045afa506002816040516106e39190610c4f565b602060405180830381855afa158015610700573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107239190610c6b565b84848151811061073557610735610b43565b6020026020010181815250505050808061074e90610cd0565b91505061066d565b5083610761826108c4565b9350935050509250929050565b600060028161077d8285610cae565b67ffffffffffffffff81111561079557610795610a3c565b6040519080825280602002602001820160405280156107be578160200160208202803683370190505b50905060005b6107ce8386610cae565b8110156108b05760006107e2826068610c84565b6107ed886024610c9b565b6107f79190610c9b565b60408051606880825260a08201909252919250600091906020820181803683370190505090506068602082016068848c0160045afa5060028160405161083d9190610c4f565b602060405180830381855afa15801561085a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061087d9190610c6b565b84848151811061088f5761088f610b43565b602002602001018181525050505080806108a890610cd0565b9150506107c4565b506108ba816108c4565b9695505050505050565b6000805b82516108d5826002610dcd565b10156108ed57806108e581610cd0565b9150506108c8565b60006108fa826002610dcd565b905080845260005b82811015610a175760005b82811015610a0457600286828151811061092957610929610b43565b60200260200101518783600161093f9190610c9b565b8151811061094f5761094f610b43565b6020026020010151604051602001610971929190918252602082015260400190565b60408051601f198184030181529082905261098b91610c4f565b602060405180830381855afa1580156109a8573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906109cb9190610c6b565b866109d7600284610cae565b815181106109e7576109e7610b43565b60209081029190910101526109fd600282610c9b565b905061090d565b5080610a0f81610cd0565b915050610902565b5083600081518110610a2b57610a2b610b43565b602002602001015192505050919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610a6357600080fd5b813567ffffffffffffffff80821115610a7e57610a7e610a3c565b604051601f8301601f19908116603f01168101908282118183101715610aa657610aa6610a3c565b81604052838152866020858801011115610abf57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215610af257600080fd5b823567ffffffffffffffff80821115610b0a57600080fd5b610b1686838701610a52565b93506020850135915080821115610b2c57600080fd5b50610b3985828601610a52565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b60005b83811015610b74578181015183820152602001610b5c565b50506000910152565b60408152600083518060408401526020610b9d8260608601838901610b59565b6060601f19601f93909301929092168401848103830185830152855192810183905285820192600091608001905b80831015610beb5784518252938301936001929092019190830190610bcb565b50979650505050505050565b600060208284031215610c0957600080fd5b81518015158114610c1957600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610c4957610c49610c20565b92915050565b60008251610c61818460208701610b59565b9190910192915050565b600060208284031215610c7d57600080fd5b5051919050565b8082028115828204841417610c4957610c49610c20565b80820180821115610c4957610c49610c20565b600082610ccb57634e487b7160e01b600052601260045260246000fd5b500490565b600060018201610ce257610ce2610c20565b5060010190565b600181815b80851115610d24578160001904821115610d0a57610d0a610c20565b80851615610d1757918102915b93841c9390800290610cee565b509250929050565b600082610d3b57506001610c49565b81610d4857506000610c49565b8160018114610d5e5760028114610d6857610d84565b6001915050610c49565b60ff841115610d7957610d79610c20565b50506001821b610c49565b5060208310610133831016604e8410600b8410161715610da7575081810a610c49565b610db18383610ce9565b8060001904821115610dc557610dc5610c20565b029392505050565b6000610c198383610d2c56fea2646970667358221220ece9d35f0dabd2ce67f2fc7b08e612bd5e3e292de94f6df90a3bb48f782fd9ef64736f6c63430008120033608060405234801561001057600080fd5b5061017d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063937f6a101461003b578063ea50d0e41461005a575b600080fd5b60405168496d2061206d6f636b60b81b81526020015b60405180910390f35b610072610068366004610082565b6001949350505050565b6040519015158152602001610051565b6000806000806040858703121561009857600080fd5b843567ffffffffffffffff808211156100b057600080fd5b818701915087601f8301126100c457600080fd5b8135818111156100d357600080fd5b8860208285010111156100e557600080fd5b60209283019650945090860135908082111561010057600080fd5b818701915087601f83011261011457600080fd5b81358181111561012357600080fd5b8860208260051b850101111561013857600080fd5b9598949750506020019450505056fea2646970667358221220dccfdb9ed1ec020c6477c07aa6b7354d591126e95a8df81bf7a547459d30b6cb64736f6c63430008120033', - ) as any; - } -} -export var RollupAbi = abi; diff --git a/yarn-project/l1-contracts/src/ethereumjs-contracts/Rollup.ts b/yarn-project/l1-contracts/src/ethereumjs-contracts/Rollup.ts new file mode 100644 index 000000000000..a21a51029cc5 --- /dev/null +++ b/yarn-project/l1-contracts/src/ethereumjs-contracts/Rollup.ts @@ -0,0 +1,42 @@ +// THIS IS GENERATED CODE, DO NOT EDIT! +/* eslint-disable */ +import { EthAddress } from '@aztec/ethereum.js/eth_address'; +import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc'; +import { Contract, ContractTxReceipt, EventLog, Options, TxCall, TxSend } from '@aztec/ethereum.js/contract'; +import * as Bytes from '@aztec/ethereum.js/contract/bytes.js'; +import abi from './RollupAbi.js'; +export type L2BlockProcessedEvent = { + blockNum: bigint; +}; +export interface L2BlockProcessedEventLog extends EventLog {} +interface RollupEvents { + L2BlockProcessed: L2BlockProcessedEvent; +} +interface RollupEventLogs { + L2BlockProcessed: L2BlockProcessedEventLog; +} +interface RollupTxEventLogs { + L2BlockProcessed: L2BlockProcessedEventLog[]; +} +export interface RollupTransactionReceipt extends ContractTxReceipt {} +interface RollupMethods { + VERIFIER(): TxCall; + process(_proof: Bytes.Bytes, _l2Block: Bytes.Bytes): TxSend; + rollupStateHash(): TxCall; +} +export interface RollupDefinition { + methods: RollupMethods; + events: RollupEvents; + eventLogs: RollupEventLogs; +} +export class Rollup extends Contract { + constructor(eth: EthereumRpc, address?: EthAddress, options?: Options) { + super(eth, abi, address, options); + } + deploy(): TxSend { + return super.deployBytecode( + '0x60a060405234801561001057600080fd5b5060405161001d9061004b565b604051809103906000f080158015610039573d6000803e3d6000fd5b506001600160a01b0316608052610058565b61019d80610ca883390190565b608051610c2f61007960003960008181604b015261016b0152610c2f6000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806308c84e70146100465780631ab9c6031461008a5780637c39d130146100a1575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61009360005481565b604051908152602001610081565b6100b46100af36600461088e565b6100b6565b005b6000806000806100c68686610237565b60005493975091955093509150158015906100e357508260005414155b1561011357600054604051632d2ef59f60e11b815260048101919091526024810184905260440160405180910390fd5b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061014957610149610969565b6020908102919091010152604051633a94343960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ea50d0e4906101a2908b9085906004016109a3565b602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e39190610a1d565b610200576040516309bde33960e01b815260040160405180910390fd5b600083815560405186917f655779015b9b95c7fd18f01ea4619ab4c31289bbe134ba85c5b20bcdeb1dabf391a25050505050505050565b813560e01c6000808061025761024e600186610a5c565b6004888861027d565b92506102668460b8888861027d565b91506102728686610327565b905092959194509250565b6040805160b880825260e082019092526000918291906020820181803683370190505090508560181c60208201538560101c60218201538560081c602282015385602382015360b485850160248301376002816040516102dd9190610a6f565b602060405180830381855afa1580156102fa573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061031d9190610a8b565b9695505050505050565b6040805161018c8082526101c082019092526000919082908260208201818036833701905050905081602086016020830137600061036586866103cd565b90508061016c6020018301526002826040516103819190610a6f565b602060405180830381855afa15801561039e573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906103c19190610a8b565b93505050505b92915050565b60006103f360405180606001604052806000815260200160008152602001600081525090565b61016c84013560e01c80825261040a600482610aa4565b6020830152600061041c600480610ac6565b836020015161042b9190610ad9565b610436906020610ad9565b8601610174013560e01c60408401525050602081015160009061045b90600290610aa4565b67ffffffffffffffff8111156104735761047361082f565b60405190808252806020026020018201604052801561049c578160200160208202803683370190505b50905060006104ad60046020610ad9565b6104b8906002610ad9565b905060006104c860046020610ad9565b6104d3906002610ad9565b6104dd9083610ac6565b8451909150610170906000906104f4906020610ad9565b61050090610174610ac6565b9050600061050f600480610ac6565b865161051c906002610ad9565b6105269190610ad9565b610531906020610ad9565b61053d90610178610ac6565b90506000876040015160206105529190610ad9565b61055c9083610ac6565b905060005b875181101561069e57604080516102a88082526102e082019092526000916020820181803683370190505090506101008d860160208301376101008d8701828a016020013760408d85018289016020013760688d8401828901606001376105ca60046002610ad9565b6105d5906020610ad9565b6105df9087610ac6565b95506105ed60046002610ad9565b6105f8906020610ad9565b6106029086610ac6565b945061060f604085610ac6565b935061061c606884610ac6565b925060028160405161062e9190610a6f565b602060405180830381855afa15801561064b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061066e9190610a8b565b89838151811061068057610680610969565b6020908102919091010152508061069681610af0565b915050610561565b506106a8876106b7565b9b9a5050505050505050505050565b6000805b82516106c8826002610bed565b10156106e057806106d881610af0565b9150506106bb565b60006106ed826002610bed565b905080845260005b8281101561080a5760005b828110156107f757600286828151811061071c5761071c610969565b6020026020010151878360016107329190610ac6565b8151811061074257610742610969565b6020026020010151604051602001610764929190918252602082015260400190565b60408051601f198184030181529082905261077e91610a6f565b602060405180830381855afa15801561079b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906107be9190610a8b565b866107ca600284610aa4565b815181106107da576107da610969565b60209081029190910101526107f0600282610ac6565b9050610700565b508061080281610af0565b9150506106f5565b508360008151811061081e5761081e610969565b602002602001015192505050919050565b634e487b7160e01b600052604160045260246000fd5b60008083601f84011261085757600080fd5b50813567ffffffffffffffff81111561086f57600080fd5b60208301915083602082850101111561088757600080fd5b9250929050565b6000806000604084860312156108a357600080fd5b833567ffffffffffffffff808211156108bb57600080fd5b818601915086601f8301126108cf57600080fd5b8135818111156108e1576108e161082f565b604051601f8201601f19908116603f011681019083821181831017156109095761090961082f565b8160405282815289602084870101111561092257600080fd5b82602086016020830137600060208483010152809750505050602086013591508082111561094f57600080fd5b5061095c86828701610845565b9497909650939450505050565b634e487b7160e01b600052603260045260246000fd5b60005b8381101561099a578181015183820152602001610982565b50506000910152565b604081526000835180604084015260206109c3826060860183890161097f565b6060601f19601f93909301929092168401848103830185830152855192810183905285820192600091608001905b80831015610a1157845182529383019360019290920191908301906109f1565b50979650505050505050565b600060208284031215610a2f57600080fd5b81518015158114610a3f57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b818103818111156103c7576103c7610a46565b60008251610a8181846020870161097f565b9190910192915050565b600060208284031215610a9d57600080fd5b5051919050565b600082610ac157634e487b7160e01b600052601260045260246000fd5b500490565b808201808211156103c7576103c7610a46565b80820281158282048414176103c7576103c7610a46565b600060018201610b0257610b02610a46565b5060010190565b600181815b80851115610b44578160001904821115610b2a57610b2a610a46565b80851615610b3757918102915b93841c9390800290610b0e565b509250929050565b600082610b5b575060016103c7565b81610b68575060006103c7565b8160018114610b7e5760028114610b8857610ba4565b60019150506103c7565b60ff841115610b9957610b99610a46565b50506001821b6103c7565b5060208310610133831016604e8410600b8410161715610bc7575081810a6103c7565b610bd18383610b09565b8060001904821115610be557610be5610a46565b029392505050565b6000610a3f8383610b4c56fea2646970667358221220c37a8febedb19354552a6af55407c01a4adb259b1b2f7f8ce2b69d053166985864736f6c63430008120033608060405234801561001057600080fd5b5061017d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063937f6a101461003b578063ea50d0e41461005a575b600080fd5b60405168496d2061206d6f636b60b81b81526020015b60405180910390f35b610072610068366004610082565b6001949350505050565b6040519015158152602001610051565b6000806000806040858703121561009857600080fd5b843567ffffffffffffffff808211156100b057600080fd5b818701915087601f8301126100c457600080fd5b8135818111156100d357600080fd5b8860208285010111156100e557600080fd5b60209283019650945090860135908082111561010057600080fd5b818701915087601f83011261011457600080fd5b81358181111561012357600080fd5b8860208260051b850101111561013857600080fd5b9598949750506020019450505056fea2646970667358221220cbafe20e80562aadc2710ca58ec11e2365028b9e1bfe5c6f0da103d7fdda728e64736f6c63430008120033', + ) as any; + } +} +export var RollupAbi = abi; diff --git a/yarn-project/l1-contracts/src/aztec-ethereumjs-contracts/RollupAbi.ts b/yarn-project/l1-contracts/src/ethereumjs-contracts/RollupAbi.ts similarity index 90% rename from yarn-project/l1-contracts/src/aztec-ethereumjs-contracts/RollupAbi.ts rename to yarn-project/l1-contracts/src/ethereumjs-contracts/RollupAbi.ts index 2c1bc7ba3630..6162c30d5454 100644 --- a/yarn-project/l1-contracts/src/aztec-ethereumjs-contracts/RollupAbi.ts +++ b/yarn-project/l1-contracts/src/ethereumjs-contracts/RollupAbi.ts @@ -32,13 +32,26 @@ export default new ContractAbi([ { indexed: true, internalType: 'uint256', - name: 'rollupBlockNumber', + name: 'blockNum', type: 'uint256', }, ], - name: 'RollupBlockProcessed', + name: 'L2BlockProcessed', type: 'event', }, + { + inputs: [], + name: 'VERIFIER', + outputs: [ + { + internalType: 'contract MockVerifier', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, { inputs: [ { @@ -48,11 +61,11 @@ export default new ContractAbi([ }, { internalType: 'bytes', - name: '_inputs', + name: '_l2Block', type: 'bytes', }, ], - name: 'processRollup', + name: 'process', outputs: [], stateMutability: 'nonpayable', type: 'function', @@ -70,17 +83,4 @@ export default new ContractAbi([ stateMutability: 'view', type: 'function', }, - { - inputs: [], - name: 'verifier', - outputs: [ - { - internalType: 'contract MockVerifier', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, ]); diff --git a/yarn-project/l1-contracts/src/ethereumjs-contracts/Yeeter.ts b/yarn-project/l1-contracts/src/ethereumjs-contracts/Yeeter.ts new file mode 100644 index 000000000000..8874fad866d7 --- /dev/null +++ b/yarn-project/l1-contracts/src/ethereumjs-contracts/Yeeter.ts @@ -0,0 +1,57 @@ +// THIS IS GENERATED CODE, DO NOT EDIT! +/* eslint-disable */ +import { EthAddress } from '@aztec/ethereum.js/eth_address'; +import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc'; +import { Contract, ContractTxReceipt, EventLog, Options, TxCall, TxSend } from '@aztec/ethereum.js/contract'; +import * as Bytes from '@aztec/ethereum.js/contract/bytes.js'; +import abi from './YeeterAbi.js'; +export type ContractDeploymentYeetEvent = { + aztecAddress: Bytes.Bytes32; + portalAddress: EthAddress; + acir: Bytes.Bytes; +}; +export type YeetEvent = { + l2blockNum: bigint; + sender: EthAddress; + blabber: Bytes.Bytes; +}; +export interface ContractDeploymentYeetEventLog + extends EventLog {} +export interface YeetEventLog extends EventLog {} +interface YeeterEvents { + ContractDeploymentYeet: ContractDeploymentYeetEvent; + Yeet: YeetEvent; +} +interface YeeterEventLogs { + ContractDeploymentYeet: ContractDeploymentYeetEventLog; + Yeet: YeetEventLog; +} +interface YeeterTxEventLogs { + ContractDeploymentYeet: ContractDeploymentYeetEventLog[]; + Yeet: YeetEventLog[]; +} +export interface YeeterTransactionReceipt extends ContractTxReceipt {} +interface YeeterMethods { + yeet(_l2blockNum: bigint, _blabber: Bytes.Bytes): TxSend; + yeetContractDeployment( + _aztecAddress: Bytes.Bytes32, + _portalAddress: EthAddress, + _acir: Bytes.Bytes, + ): TxSend; +} +export interface YeeterDefinition { + methods: YeeterMethods; + events: YeeterEvents; + eventLogs: YeeterEventLogs; +} +export class Yeeter extends Contract { + constructor(eth: EthereumRpc, address?: EthAddress, options?: Options) { + super(eth, abi, address, options); + } + deploy(): TxSend { + return super.deployBytecode( + '0x608060405234801561001057600080fd5b50610258806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634bcfab1e1461003b5780639ac5c19314610050575b600080fd5b61004e61004936600461013f565b610063565b005b61004e61005e3660046101a7565b6100ad565b826001600160a01b0316847f7096e387ade580c7ae4f990e89cea632c2c114edde263b269f456f896a595b2a848460405161009f9291906101f3565b60405180910390a350505050565b336001600160a01b0316837f6b104311c3f2fcdacda72ada5cd1341c211de62acdedc2e26b94d3cc8aaea2bb84846040516100e99291906101f3565b60405180910390a3505050565b60008083601f84011261010857600080fd5b50813567ffffffffffffffff81111561012057600080fd5b60208301915083602082850101111561013857600080fd5b9250929050565b6000806000806060858703121561015557600080fd5b8435935060208501356001600160a01b038116811461017357600080fd5b9250604085013567ffffffffffffffff81111561018f57600080fd5b61019b878288016100f6565b95989497509550505050565b6000806000604084860312156101bc57600080fd5b83359250602084013567ffffffffffffffff8111156101da57600080fd5b6101e6868287016100f6565b9497909650939450505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea2646970667358221220573c8b4c799070891b5f6b83a5b09e80c2ebee660655d21e1a8c1eaf674405b764736f6c63430008120033', + ) as any; + } +} +export var YeeterAbi = abi; diff --git a/yarn-project/l1-contracts/src/ethereumjs-contracts/YeeterAbi.ts b/yarn-project/l1-contracts/src/ethereumjs-contracts/YeeterAbi.ts new file mode 100644 index 000000000000..802f19d89e33 --- /dev/null +++ b/yarn-project/l1-contracts/src/ethereumjs-contracts/YeeterAbi.ts @@ -0,0 +1,94 @@ +import { ContractAbi } from '@aztec/ethereum.js/contract'; +export default new ContractAbi([ + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'aztecAddress', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'portalAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes', + name: 'acir', + type: 'bytes', + }, + ], + name: 'ContractDeploymentYeet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'l2blockNum', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes', + name: 'blabber', + type: 'bytes', + }, + ], + name: 'Yeet', + type: 'event', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '_l2blockNum', + type: 'uint256', + }, + { + internalType: 'bytes', + name: '_blabber', + type: 'bytes', + }, + ], + name: 'yeet', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: '_aztecAddress', + type: 'bytes32', + }, + { + internalType: 'address', + name: '_portalAddress', + type: 'address', + }, + { + internalType: 'bytes', + name: '_acir', + type: 'bytes', + }, + ], + name: 'yeetContractDeployment', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, +]); diff --git a/yarn-project/l1-contracts/src/index.ts b/yarn-project/l1-contracts/src/index.ts index 517b33aeefe1..dc54957f3ff9 100644 --- a/yarn-project/l1-contracts/src/index.ts +++ b/yarn-project/l1-contracts/src/index.ts @@ -1,6 +1,21 @@ +import { EthAddress } from '@aztec/ethereum.js/eth_address'; + +export const INITIAL_ROLLUP_ID = 1; + +/** + * Rollup contract addresses. + */ export interface L1Addresses { - rollupContract: string; - feeDistributor: string; + /** + * Rollup contract address. + */ + rollupContract: EthAddress; + + /** + * Yeeter contract address. + */ + yeeterContract: EthAddress; } -export * from './aztec-ethereumjs-contracts/Rollup.js'; +export * from './ethereumjs-contracts/Rollup.js'; +export * from './ethereumjs-contracts/Yeeter.js'; diff --git a/yarn-project/l1-contracts/src/viem-abis/RollupAbi.ts b/yarn-project/l1-contracts/src/viem-abis/RollupAbi.ts new file mode 100644 index 000000000000..4e2bd8a62200 --- /dev/null +++ b/yarn-project/l1-contracts/src/viem-abis/RollupAbi.ts @@ -0,0 +1,88 @@ +/** + * Rollup ABI for viem. + */ +export const RollupAbi = [ + { + inputs: [], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [], + name: 'InvalidProof', + type: 'error', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'expected', + type: 'bytes32', + }, + { + internalType: 'bytes32', + name: 'actual', + type: 'bytes32', + }, + ], + name: 'InvalidStateHash', + type: 'error', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'blockNum', + type: 'uint256', + }, + ], + name: 'L2BlockProcessed', + type: 'event', + }, + { + inputs: [], + name: 'VERIFIER', + outputs: [ + { + internalType: 'contract MockVerifier', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes', + name: '_proof', + type: 'bytes', + }, + { + internalType: 'bytes', + name: '_l2Block', + type: 'bytes', + }, + ], + name: 'process', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'rollupStateHash', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, +] as const; diff --git a/yarn-project/l1-contracts/src/viem-abis/YeeterAbi.ts b/yarn-project/l1-contracts/src/viem-abis/YeeterAbi.ts new file mode 100644 index 000000000000..5f543ec14d99 --- /dev/null +++ b/yarn-project/l1-contracts/src/viem-abis/YeeterAbi.ts @@ -0,0 +1,96 @@ +/** + * Yeeter ABI for viem. + */ +export const YeeterAbi = [ + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'aztecAddress', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'portalAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes', + name: 'acir', + type: 'bytes', + }, + ], + name: 'ContractDeploymentYeet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'l2blockNum', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes', + name: 'blabber', + type: 'bytes', + }, + ], + name: 'Yeet', + type: 'event', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '_l2blockNum', + type: 'uint256', + }, + { + internalType: 'bytes', + name: '_blabber', + type: 'bytes', + }, + ], + name: 'yeet', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: '_aztecAddress', + type: 'bytes32', + }, + { + internalType: 'address', + name: '_portalAddress', + type: 'address', + }, + { + internalType: 'bytes', + name: '_acir', + type: 'bytes', + }, + ], + name: 'yeetContractDeployment', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const; diff --git a/yarn-project/l1-contracts/src/viem-abis/index.ts b/yarn-project/l1-contracts/src/viem-abis/index.ts new file mode 100644 index 000000000000..f751fc1b4475 --- /dev/null +++ b/yarn-project/l1-contracts/src/viem-abis/index.ts @@ -0,0 +1,2 @@ +export * from './RollupAbi.js'; +export * from './YeeterAbi.js'; diff --git a/yarn-project/merkle-tree/src/merkle_tree.ts b/yarn-project/merkle-tree/src/merkle_tree.ts index e300f28d8390..5984d225b8d8 100644 --- a/yarn-project/merkle-tree/src/merkle_tree.ts +++ b/yarn-project/merkle-tree/src/merkle_tree.ts @@ -1,41 +1,5 @@ import { SiblingPath } from './sibling_path/sibling_path.js'; -/** - * Defines the possible Merkle tree IDs. - */ -export enum MerkleTreeId { - CONTRACT_TREE = 0, - CONTRACT_TREE_ROOTS_TREE = 1, - NULLIFIER_TREE = 2, -} - -/** - * Defines the depths of the various merkle trees. - */ -export enum MerkleTreeDepths { - CONTRACT_TREE = 32, - CONTRACT_TREE_ROOTS_TREE = 8, - NULLIFIER_TREE = 32, -} - -/** - * Defines tree information. - */ -export interface TreeInfo { - /** - * The tree ID. - */ - treeId: MerkleTreeId; - /** - * The tree root. - */ - root: Buffer; - /** - * The number of leaves in the tree. - */ - size: bigint; -} - /** * Defines the interface for a source of sibling paths. */ @@ -53,14 +17,3 @@ export interface MerkleTree extends SiblingPathSource { commit(): Promise; rollback(): Promise; } - -/** - * Defines the interface for a database that stores Merkle trees. - */ -export interface MerkleTreeDb { - getTreeInfo(treeId: MerkleTreeId): Promise; - appendLeaves(treeId: MerkleTreeId, leaves: Buffer[]): Promise; - getSiblingPath(treeId: MerkleTreeId, index: bigint): Promise; - commit(): Promise; - rollback(): Promise; -} diff --git a/yarn-project/p2p/package.json b/yarn-project/p2p/package.json index 71d0a5ce6591..dba27766ad44 100644 --- a/yarn-project/p2p/package.json +++ b/yarn-project/p2p/package.json @@ -15,6 +15,7 @@ "start:dev": "tsc-watch -p tsconfig.dest.json --onSuccess 'yarn start'", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", + "formatting:fix": "run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" }, "jest": { @@ -32,6 +33,7 @@ }, "dependencies": { "@aztec/archiver": "workspace:^", + "@aztec/circuits.js": "workspace:^", "@aztec/foundation": "workspace:^", "sha3": "^2.1.4", "tslib": "^2.4.0" diff --git a/yarn-project/p2p/src/client/mocks.ts b/yarn-project/p2p/src/client/mocks.ts index 55427a3d6bc1..4f2ea6bcf380 100644 --- a/yarn-project/p2p/src/client/mocks.ts +++ b/yarn-project/p2p/src/client/mocks.ts @@ -1,16 +1,9 @@ -import { randomBytes } from 'crypto'; -import { - L2BlockSource, - L2Block, - ContractData, - randomContractData, - randomAppendOnlyTreeSnapshot, - L2BlockSourceSyncStatus, -} from '@aztec/archiver'; -import { AccumulatedTxData, Tx } from './tx.js'; +import { L2Block, L2BlockSource, mockRandomL2Block } from '@aztec/archiver'; +import { makePrivateKernelPublicInputs } from '@aztec/circuits.js/factories'; +import { Tx } from './tx.js'; export const MockTx = () => { - return new Tx(AccumulatedTxData.random()); + return new Tx(makePrivateKernelPublicInputs()); }; export class MockBlockSource implements L2BlockSource { @@ -19,7 +12,7 @@ export class MockBlockSource implements L2BlockSource { constructor(private numBlocks = 100) { this.l2Blocks = []; for (let i = 0; i < this.numBlocks; i++) { - this.l2Blocks.push(new MockBlock(i)); + this.l2Blocks.push(mockRandomL2Block(i)); } } @@ -31,13 +24,6 @@ export class MockBlockSource implements L2BlockSource { return Promise.resolve(this.l2Blocks.slice(from, from + take)); } - public getSyncStatus(): Promise { - return Promise.resolve({ - syncedToBlock: this.numBlocks, - latestBlock: this.numBlocks, - } as L2BlockSourceSyncStatus); - } - public start(): Promise { return Promise.resolve(); } @@ -46,34 +32,3 @@ export class MockBlockSource implements L2BlockSource { return Promise.resolve(); } } - -export class MockBlock extends L2Block { - constructor(private _id: number) { - const newNullifiers = [randomBytes(32), randomBytes(32), randomBytes(32), randomBytes(32)]; - const newCommitments = [randomBytes(32), randomBytes(32), randomBytes(32), randomBytes(32)]; - const newContracts: Buffer[] = [randomBytes(32)]; - const newContractsData: ContractData[] = [randomContractData()]; - - super( - _id, - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(0), - randomAppendOnlyTreeSnapshot(newCommitments.length), - randomAppendOnlyTreeSnapshot(newNullifiers.length), - randomAppendOnlyTreeSnapshot(newContracts.length), - randomAppendOnlyTreeSnapshot(1), - randomAppendOnlyTreeSnapshot(1), - newCommitments, - newNullifiers, - newContracts, - newContractsData, - ); - } - - get settlementTimestamp() { - return Date.now(); - } -} diff --git a/yarn-project/p2p/src/client/p2p_client.test.ts b/yarn-project/p2p/src/client/p2p_client.test.ts index 23831004bbcf..bfc0cea79ce8 100644 --- a/yarn-project/p2p/src/client/p2p_client.test.ts +++ b/yarn-project/p2p/src/client/p2p_client.test.ts @@ -1,7 +1,7 @@ import { expect, jest } from '@jest/globals'; import { L2BlockSource } from '@aztec/archiver'; -import { P2PCLient } from './p2p_client.js'; +import { P2PClient } from './p2p_client.js'; import { TxPool } from '../tx_pool/index.js'; import { MockBlockSource } from './mocks.js'; import { MockTx } from './mocks.js'; @@ -29,7 +29,7 @@ describe('In-Memory P2P Client', () => { }); it('can start & stop', async () => { - const client = new P2PCLient(blockSource, txPool); + const client = new P2PClient(blockSource, txPool); expect(await client.isReady()).toEqual(false); await client.start(); @@ -40,7 +40,7 @@ describe('In-Memory P2P Client', () => { }); it('adds txs to pool', async () => { - const client = new P2PCLient(blockSource, txPool); + const client = new P2PClient(blockSource, txPool); await client.start(); const tx1 = MockTx(); const tx2 = MockTx(); @@ -52,7 +52,7 @@ describe('In-Memory P2P Client', () => { }); it('rejects txs after being stopped', async () => { - const client = new P2PCLient(blockSource, txPool); + const client = new P2PClient(blockSource, txPool); await client.start(); const tx1 = MockTx(); const tx2 = MockTx(); diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index c847979a83fe..58a3d18a0613 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -2,21 +2,33 @@ import { L2Block, L2BlockSource, L2BlockDownloader } from '@aztec/archiver'; import { InMemoryTxPool } from '../tx_pool/memory_tx_pool.js'; import { TxPool } from '../tx_pool/index.js'; -import { Tx } from './tx.js'; +import { createTxIds, Tx } from './tx.js'; import { createDebugLogger } from '@aztec/foundation'; -const TAKE_NUM = 1; - /** * Enum defining the possible states of the p2p client. */ -enum P2PClientState { +export enum P2PClientState { IDLE, SYNCHING, RUNNING, STOPPED, } +/** + * The synchronisation status of the P2P client. + */ +export interface P2PSyncState { + /** + * The current state of the p2p client. + */ + state: P2PClientState; + /** + * The block number that the p2p client is synced to. + */ + syncedToL2Block: number; +} + /** * Interface of a P2P client. **/ @@ -49,12 +61,17 @@ export interface P2P { * @returns A boolean flag indicating readiness. */ isReady(): Promise; + + /* + * Returns the current status of the p2p client. + */ + getStatus(): Promise; } /** * The P2P client implementation. */ -export class P2PCLient implements P2P { +export class P2PClient implements P2P { /** * L2 Block download that p2p client uses to stay in sync with latest blocks. */ @@ -68,12 +85,12 @@ export class P2PCLient implements P2P { /** * The JS promise that will be running to keep the client's data in sync. Can be interrupted if the client is stopped. */ - private runningSyncPromise!: Promise; + private runningPromise!: Promise; /** * Store the ID of the latest block the client has synced to. */ - private syncedBlockNum = -1; + private currentL2BlockNum = 0; private currentState = P2PClientState.IDLE; private syncPromise = Promise.resolve(); @@ -91,7 +108,7 @@ export class P2PCLient implements P2P { private txPool: TxPool = new InMemoryTxPool(), private log = createDebugLogger('aztec:p2p'), ) { - this.blockDownloader = new L2BlockDownloader(l2BlockSource, TAKE_NUM); + this.blockDownloader = new L2BlockDownloader(l2BlockSource, 1000, 100); } /** @@ -109,30 +126,32 @@ export class P2PCLient implements P2P { // get the current latest block number this.latestBlockNumberAtStart = await this.l2BlockSource.getLatestBlockNum(); - if (this.syncedBlockNum >= this.latestBlockNumberAtStart) { - // if no blocks to be retrieved, go straight to running - this.setCurrentState(P2PClientState.RUNNING); - this.syncPromise = Promise.resolve(); - this.log(`already synched to latest block ${this.latestBlockNumberAtStart}`); - } else { + const blockToDownloadFrom = this.currentL2BlockNum + 1; + + // if there are blocks to be retrieved, go to a synching state + if (blockToDownloadFrom <= this.latestBlockNumberAtStart) { this.setCurrentState(P2PClientState.SYNCHING); this.syncPromise = new Promise(resolve => { this.syncResolve = resolve; }); - this.log(`starting sync from ${this.syncedBlockNum}, latest block ${this.latestBlockNumberAtStart}`); + this.log(`Starting sync from ${blockToDownloadFrom}, latest block ${this.latestBlockNumberAtStart}`); + } else { + // if no blocks to be retrieved, go straight to running + this.setCurrentState(P2PClientState.RUNNING); + this.syncPromise = Promise.resolve(); + this.log(`Next block ${blockToDownloadFrom} already beyond latest block at ${this.latestBlockNumberAtStart}`); } // start looking for further blocks const blockProcess = async () => { while (!this.stopping) { const blocks = await this.blockDownloader.getL2Blocks(); - await this.processBlocks(blocks); + await this.handleL2Blocks(blocks); } }; - this.runningSyncPromise = blockProcess(); - const blockToDownloadFrom = this.syncedBlockNum + 1; + this.runningPromise = blockProcess(); this.blockDownloader.start(blockToDownloadFrom); - this.log(`started block downloader from block ${blockToDownloadFrom}`); + this.log(`Started block downloader from block ${blockToDownloadFrom}`); return this.syncPromise; } @@ -141,10 +160,10 @@ export class P2PCLient implements P2P { * 'ready' will now return 'false' and the running promise that keeps the client synced is interrupted. */ public async stop() { - this.log('stopping p2p client...'); + this.log('Stopping p2p client...'); this.stopping = true; await this.blockDownloader.stop(); - await this.runningSyncPromise; + await this.runningPromise; this.setCurrentState(P2PClientState.STOPPED); } @@ -182,18 +201,18 @@ export class P2PCLient implements P2P { * @returns Block number of latest L2 Block we've synced with. */ public getSyncedBlockNum() { - return this.syncedBlockNum; + return this.currentL2BlockNum; } /** * Method to check the status the p2p client. * @returns Information about p2p client status: state & syncedToBlockNum. */ - public getStatus() { - return { + public getStatus(): Promise { + return Promise.resolve({ state: this.currentState, - syncedToBlockNum: this.syncedBlockNum, - }; + syncedToL2Block: this.currentL2BlockNum, + } as P2PSyncState); } /** @@ -203,8 +222,11 @@ export class P2PCLient implements P2P { */ private reconcileTxPool(blocks: L2Block[]): Promise { for (let i = 0; i < blocks.length; i++) { - const { newContracts } = blocks[i]; - this.txPool.deleteTxs(newContracts?.map((data: Buffer) => Tx.createTxId(data)) || []); + const txIds = createTxIds(blocks[i]); + for (let i = 0; i < txIds.length; i++) { + this.log(`Deleting tx id ${txIds[i].toString('hex')} from tx pool`); + } + this.txPool.deleteTxs(txIds); } return Promise.resolve(); } @@ -214,14 +236,14 @@ export class P2PCLient implements P2P { * @param blocks - A list of existing blocks with txs that the P2P client needs to ensure the tx pool is reconciled with. * @returns Empty promise. */ - private async processBlocks(blocks: L2Block[]): Promise { + private async handleL2Blocks(blocks: L2Block[]): Promise { if (!blocks.length) { return Promise.resolve(); } await this.reconcileTxPool(blocks); - this.syncedBlockNum = blocks[blocks.length - 1].number; - this.log(`synched to block ${this.syncedBlockNum}`); - if (this.currentState === P2PClientState.SYNCHING && this.syncedBlockNum >= this.latestBlockNumberAtStart) { + this.currentL2BlockNum = blocks[blocks.length - 1].number; + this.log(`Synched to block ${this.currentL2BlockNum}`); + if (this.currentState === P2PClientState.SYNCHING && this.currentL2BlockNum >= this.latestBlockNumberAtStart) { this.setCurrentState(P2PClientState.RUNNING); if (this.syncResolve !== undefined) { this.syncResolve(); @@ -235,6 +257,6 @@ export class P2PCLient implements P2P { */ private setCurrentState(newState: P2PClientState) { this.currentState = newState; - this.log(`moved to state ${P2PClientState[this.currentState]}`); + this.log(`Moved to state ${P2PClientState[this.currentState]}`); } } diff --git a/yarn-project/p2p/src/client/tx.ts b/yarn-project/p2p/src/client/tx.ts index b27d15b109aa..f16cd5e81d02 100644 --- a/yarn-project/p2p/src/client/tx.ts +++ b/yarn-project/p2p/src/client/tx.ts @@ -1,44 +1,20 @@ -import { randomBytes } from 'crypto'; +import { L2Block } from '@aztec/archiver'; +import { + KERNEL_NEW_COMMITMENTS_LENGTH, + KERNEL_NEW_CONTRACTS_LENGTH, + KERNEL_NEW_NULLIFIERS_LENGTH, + PrivateKernelPublicInputs, +} from '@aztec/circuits.js'; import { Keccak } from 'sha3'; const hash = new Keccak(256); -/** - * Accumulated data of an A3 transaction. - */ -export class AccumulatedTxData { - constructor( - public newCommitments: Buffer[], - public newNullifiers: Buffer[], - public privateCallStack: Buffer[], - public publicCallStack: Buffer[], - public l1MsgStack: Buffer[], - public newContracts: Buffer[], - public optionallyRevealedData: Buffer[], - public aggregationObject?: object, - public callCount?: number, - ) {} - - public static random() { - return new AccumulatedTxData( - [randomBytes(32)], - [randomBytes(32)], - [randomBytes(32)], - [randomBytes(32)], - [randomBytes(32)], - [randomBytes(32)], - [randomBytes(32)], - undefined, - undefined, - ); - } -} - /** * The interface of an L2 transaction. */ export class Tx { - constructor(private txData: AccumulatedTxData) {} + private _id?: Buffer; + constructor(private txData: PrivateKernelPublicInputs) {} /** * Construct & return transaction ID. @@ -46,18 +22,55 @@ export class Tx { * @returns The transaction's id. */ get txId() { - const constractTxData = this.txData.newContracts[0]; - hash.reset(); - return hash.update(constractTxData).digest(); + if (!this._id) { + this._id = Tx.createTxId(this); + } + return this._id; + } + + get data() { + return this.txData; } /** * Utility function to generate tx ID. - * @param txData - Binary representation of the tx data. + * @param tx - The transaction from which to generate the id. * @returns A hash of the tx data that identifies the tx. */ - static createTxId(txData: Buffer) { + static createTxId(tx: Tx) { hash.reset(); - return hash.update(txData).digest(); + const dataToHash = Buffer.concat( + [ + tx.txData.end.newCommitments.map(x => x.toBuffer()), + tx.txData.end.newNullifiers.map(x => x.toBuffer()), + tx.txData.end.newContracts.map(x => x.functionTreeRoot.toBuffer()), + ].flat(), + ); + return hash.update(dataToHash).digest(); + } +} + +export function createTxIds(block: L2Block) { + hash.reset(); + let i = 0; + const numTxs = Math.floor(block.newCommitments.length / KERNEL_NEW_COMMITMENTS_LENGTH); + const txIds: Buffer[] = []; + while (i < numTxs) { + const dataToHash = Buffer.concat( + [ + block.newCommitments + .slice(i * KERNEL_NEW_COMMITMENTS_LENGTH, i * KERNEL_NEW_COMMITMENTS_LENGTH + KERNEL_NEW_COMMITMENTS_LENGTH) + .map(x => x.toBuffer()), + block.newNullifiers + .slice(i * KERNEL_NEW_NULLIFIERS_LENGTH, i * KERNEL_NEW_NULLIFIERS_LENGTH + KERNEL_NEW_NULLIFIERS_LENGTH) + .map(x => x.toBuffer()), + block.newContracts + .slice(i * KERNEL_NEW_CONTRACTS_LENGTH, i * KERNEL_NEW_CONTRACTS_LENGTH + KERNEL_NEW_CONTRACTS_LENGTH) + .map(x => x.toBuffer()), + ].flat(), + ); + txIds.push(hash.update(dataToHash).digest()); + i++; } + return txIds; } diff --git a/yarn-project/p2p/tsconfig.dest.json b/yarn-project/p2p/tsconfig.dest.json index f454c8daf89b..502cbe342af6 100644 --- a/yarn-project/p2p/tsconfig.dest.json +++ b/yarn-project/p2p/tsconfig.dest.json @@ -1,12 +1,9 @@ { "extends": ".", "references": [ - { - "path": "../archiver/tsconfig.dest.json" - }, - { - "path": "../foundation/tsconfig.dest.json" - } + { "path": "../archiver/tsconfig.dest.json" }, + { "path": "../circuits.js/tsconfig.dest.json" }, + { "path": "../foundation/tsconfig.dest.json" } ], "exclude": ["**/*.test.*", "**/fixtures/*"] } diff --git a/yarn-project/p2p/tsconfig.json b/yarn-project/p2p/tsconfig.json index ca129bed4417..85109fc77b20 100644 --- a/yarn-project/p2p/tsconfig.json +++ b/yarn-project/p2p/tsconfig.json @@ -8,9 +8,9 @@ "types": ["node", "jest"] }, "references": [ - { - "path": "../archiver/tsconfig.dest.json" - } + { "path": "../archiver/tsconfig.dest.json" }, + { "path": "../circuits.js/tsconfig.dest.json" }, + { "path": "../foundation/tsconfig.dest.json" } ], "include": ["src"] } diff --git a/yarn-project/package.json b/yarn-project/package.json index ecc6350ba1ec..2a75807ed9ad 100644 --- a/yarn-project/package.json +++ b/yarn-project/package.json @@ -4,7 +4,8 @@ "private": true, "scripts": { "docs": "typedoc --out docs/dist && cd docs && yarn serve", - "formatting": "yarn workspaces foreach run formatting" + "formatting": "yarn workspaces foreach run formatting", + "formatting:fix": "yarn workspaces foreach run formatting:fix" }, "workspaces": [ "acir-simulator", @@ -12,6 +13,7 @@ "aztec-cli", "aztec-rpc", "aztec.js", + "circuits.js", "docs", "end-to-end", "ethereum.js", @@ -26,7 +28,8 @@ "prover-client", "aztec-node", "sequencer-client", - "world-state" + "world-state", + ".yalc/*/*" ], "prettier": "@aztec/foundation/prettier", "devDependencies": { @@ -34,5 +37,8 @@ "prettier": "^2.7.1", "typedoc": "^0.23.26", "typescript": "^4.9.5" + }, + "comments": { + "resolutions": "Yarn has a bug where it does not load resolutions from packages in a workspace, so those need to be hoisted here. See https://github.com/yarnpkg/yarn/issues/5039." } } diff --git a/yarn-project/sequencer-client/package.json b/yarn-project/sequencer-client/package.json index c4ee48092cbe..9b608a93e3b8 100644 --- a/yarn-project/sequencer-client/package.json +++ b/yarn-project/sequencer-client/package.json @@ -13,7 +13,7 @@ "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", - "formatting:fix": "run -T prettier -w ./src && run -T eslint --max-warnings 0 ./src", + "formatting:fix": "run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests", "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"", "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json" @@ -33,8 +33,12 @@ }, "dependencies": { "@aztec/archiver": "workspace:^", + "@aztec/circuits.js": "workspace:^", "@aztec/ethereum.js": "workspace:^", + "@aztec/foundation": "workspace:^", "@aztec/l1-contracts": "workspace:^", + "@aztec/p2p": "workspace:^", + "@aztec/world-state": "workspace:^", "tslib": "^2.4.0" }, "devDependencies": { diff --git a/yarn-project/sequencer-client/src/client/index.ts b/yarn-project/sequencer-client/src/client/index.ts new file mode 100644 index 000000000000..a8d5c7967e7c --- /dev/null +++ b/yarn-project/sequencer-client/src/client/index.ts @@ -0,0 +1 @@ +export * from './sequencer-client.js'; diff --git a/yarn-project/sequencer-client/src/client/sequencer-client.ts b/yarn-project/sequencer-client/src/client/sequencer-client.ts new file mode 100644 index 000000000000..fe0db9e8f2a1 --- /dev/null +++ b/yarn-project/sequencer-client/src/client/sequencer-client.ts @@ -0,0 +1,25 @@ +import { P2P } from '@aztec/p2p'; +import { WorldStateSynchroniser } from '@aztec/world-state'; +import { getL2BlockPublisher, L2BlockPublisher, Sequencer, SequencerClientConfig } from '../index.js'; + +/** + * Encapsulates the full sequencer and publisher. + */ +export class SequencerClient { + constructor(private publisher: L2BlockPublisher, private sequencer: Sequencer) {} + + public static async new( + config: SequencerClientConfig, + p2pClient: P2P, + worldStateSynchroniser: WorldStateSynchroniser, + ) { + const publisher = getL2BlockPublisher(config); + const sequencer = new Sequencer(publisher, p2pClient, worldStateSynchroniser, config); + await sequencer.start(); + return new SequencerClient(publisher, sequencer); + } + + public async stop() { + await this.sequencer.stop(); + } +} diff --git a/yarn-project/sequencer-client/src/config.ts b/yarn-project/sequencer-client/src/config.ts deleted file mode 100644 index d3596f7793bb..000000000000 --- a/yarn-project/sequencer-client/src/config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { L1Addresses } from '@aztec/l1-contracts'; - -export interface Config extends L1Addresses { - sequencerPrivateKey: string; - ethereumHost: string; - requiredConfirmations: number; -} diff --git a/yarn-project/sequencer-client/src/deps/running_promise.ts b/yarn-project/sequencer-client/src/deps/running_promise.ts new file mode 100644 index 000000000000..8c52f464ef3c --- /dev/null +++ b/yarn-project/sequencer-client/src/deps/running_promise.ts @@ -0,0 +1,53 @@ +// yarn-project/data-archiver/src/polling_rollup_emitter.ts +export class RunningPromise { + private running = false; + private runningPromise = Promise.resolve(); + private interruptPromise = Promise.resolve(); + private interruptResolve = () => {}; + + private pollingInterval: number; + private includeRunningTime: boolean; + + constructor(private fn: () => Promise, opts?: { pollingInterval?: number; includeRunningTime?: boolean }) { + this.pollingInterval = opts?.pollingInterval ?? 10_000; + this.includeRunningTime = opts?.includeRunningTime ?? false; + } + + /** + * Starts the running promise. + */ + public start() { + this.running = true; + this.interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); + + const poll = async () => { + while (this.running) { + const start = Date.now(); + await this.fn(); + const elapsed = Date.now() - start; + const sleepTime = this.includeRunningTime ? Math.max(this.pollingInterval - elapsed, 0) : this.pollingInterval; + await this.interruptableSleep(sleepTime); + } + }; + this.runningPromise = poll(); + } + + async stop(): Promise { + this.running = false; + this.interruptResolve(); + await this.runningPromise; + } + + private async interruptableSleep(timeInMs: number) { + let timeout!: NodeJS.Timeout; + const sleepPromise = new Promise(resolve => { + timeout = setTimeout(resolve, timeInMs); + }); + await Promise.race([sleepPromise, this.interruptPromise]); + clearTimeout(timeout); + } + + public isRunning() { + return this.running; + } +} diff --git a/yarn-project/sequencer-client/src/index.ts b/yarn-project/sequencer-client/src/index.ts index f563a520f964..2bb606eccf76 100644 --- a/yarn-project/sequencer-client/src/index.ts +++ b/yarn-project/sequencer-client/src/index.ts @@ -1,4 +1,8 @@ -/** - * A placeholder for the Sequencer Client. - */ -export class SequencerClient {} +import { SequencerConfig } from './sequencer/config.js'; +import { PublisherConfig, TxSenderConfig } from './publisher/config.js'; + +export * from './sequencer/index.js'; +export * from './publisher/index.js'; +export * from './client/index.js'; + +export type SequencerClientConfig = PublisherConfig & TxSenderConfig & SequencerConfig; diff --git a/yarn-project/sequencer-client/src/prover/index.ts b/yarn-project/sequencer-client/src/prover/index.ts new file mode 100644 index 000000000000..91dcf5df0e6a --- /dev/null +++ b/yarn-project/sequencer-client/src/prover/index.ts @@ -0,0 +1,14 @@ +import { + BaseRollupInputs, + BaseRollupPublicInputs, + MergeRollupInputs, + MergeRollupPublicInputs, + RootRollupInputs, + RootRollupPublicInputs, +} from '@aztec/circuits.js'; + +export interface Prover { + baseRollupCircuit(input: BaseRollupInputs): Promise; + mergeRollupCircuit(input: MergeRollupInputs): Promise; + rootRollupCircuit(input: RootRollupInputs): Promise; +} diff --git a/yarn-project/sequencer-client/src/prover/mock.ts b/yarn-project/sequencer-client/src/prover/mock.ts new file mode 100644 index 000000000000..4606b8170a46 --- /dev/null +++ b/yarn-project/sequencer-client/src/prover/mock.ts @@ -0,0 +1,23 @@ +import { + BaseRollupInputs, + BaseRollupPublicInputs, + MergeRollupInputs, + MergeRollupPublicInputs, + RootRollupInputs, + RootRollupPublicInputs, +} from '@aztec/circuits.js'; +import { Prover } from './index.js'; + +/* eslint-disable */ + +export class MockProver implements Prover { + baseRollupCircuit(input: BaseRollupInputs): Promise { + throw new Error('Method not implemented.'); + } + mergeRollupCircuit(input: MergeRollupInputs): Promise { + throw new Error('Method not implemented.'); + } + rootRollupCircuit(input: RootRollupInputs): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/yarn-project/sequencer-client/src/publisher/config.ts b/yarn-project/sequencer-client/src/publisher/config.ts new file mode 100644 index 000000000000..1b4dbd5423a0 --- /dev/null +++ b/yarn-project/sequencer-client/src/publisher/config.ts @@ -0,0 +1,26 @@ +import { L1Addresses } from '@aztec/l1-contracts'; + +/** + * The configuration of the rollup transaction publisher. + */ +export interface TxSenderConfig extends L1Addresses { + /** + * The private key to be used by the publisher. + */ + publisherPrivateKey: Buffer; + /** + * The RPC Url of the etheraum host. + */ + rpcUrl: string; + /** + * The number of confirmations required. + */ + requiredConfirmations: number; +} + +export interface PublisherConfig { + /** + * The interval to wait between publish retries. + */ + retryIntervalMs: number; +} diff --git a/yarn-project/sequencer-client/src/publisher/aztec-ethereumjs-tx-sender.ts b/yarn-project/sequencer-client/src/publisher/ethereumjs-tx-sender.ts similarity index 62% rename from yarn-project/sequencer-client/src/publisher/aztec-ethereumjs-tx-sender.ts rename to yarn-project/sequencer-client/src/publisher/ethereumjs-tx-sender.ts index f8e00e2694db..724522f5347b 100644 --- a/yarn-project/sequencer-client/src/publisher/aztec-ethereumjs-tx-sender.ts +++ b/yarn-project/sequencer-client/src/publisher/ethereumjs-tx-sender.ts @@ -1,25 +1,23 @@ -import { EthAddress } from '@aztec/ethereum.js/eth_address'; import { EthereumRpc, TxHash, waitForTxReceipt } from '@aztec/ethereum.js/eth_rpc'; import { WalletProvider } from '@aztec/ethereum.js/provider'; import { Rollup } from '@aztec/l1-contracts'; -import { Config } from '../config.js'; -import { hexStringToBuffer } from '../utils.js'; +import { TxSenderConfig } from './config.js'; import { L1ProcessRollupArgs, PublisherTxSender } from './l2-block-publisher.js'; /** * Pushes transactions to the L1 rollup contract using the custom aztec/ethereum.js library. */ -export class AztecEthereumjsTxSender implements PublisherTxSender { +export class EthereumjsTxSender implements PublisherTxSender { private ethRpc: EthereumRpc; private rollupContract: Rollup; private confirmations: number; - constructor(config: Config) { - const { ethereumHost, sequencerPrivateKey, rollupContract: rollupContractAddress, requiredConfirmations } = config; - const provider = WalletProvider.fromHost(ethereumHost); - provider.addAccount(hexStringToBuffer(sequencerPrivateKey)); + constructor(config: TxSenderConfig) { + const { rpcUrl, publisherPrivateKey, rollupContract: rollupContractAddress, requiredConfirmations } = config; + const provider = WalletProvider.fromHost(rpcUrl); + provider.addAccount(publisherPrivateKey); this.ethRpc = new EthereumRpc(provider); - this.rollupContract = new Rollup(this.ethRpc, EthAddress.fromString(rollupContractAddress), { + this.rollupContract = new Rollup(this.ethRpc, rollupContractAddress, { from: provider.getAccount(0), }); this.confirmations = requiredConfirmations; @@ -32,7 +30,7 @@ export class AztecEthereumjsTxSender implements PublisherTxSender { } async sendTransaction(encodedData: L1ProcessRollupArgs): Promise { - const methodCall = this.rollupContract.methods.processRollup(encodedData.proof, encodedData.inputs); + const methodCall = this.rollupContract.methods.process(encodedData.proof, encodedData.inputs); const gas = await methodCall.estimateGas(); return methodCall .send({ gas }) diff --git a/yarn-project/sequencer-client/src/publisher/index.ts b/yarn-project/sequencer-client/src/publisher/index.ts index b903b10a5205..7ad8521757ea 100644 --- a/yarn-project/sequencer-client/src/publisher/index.ts +++ b/yarn-project/sequencer-client/src/publisher/index.ts @@ -1,9 +1,10 @@ -import { Config } from '../config.js'; -import { AztecEthereumjsTxSender } from './aztec-ethereumjs-tx-sender.js'; +import { PublisherConfig, TxSenderConfig } from './config.js'; +import { EthereumjsTxSender } from './ethereumjs-tx-sender.js'; import { L2BlockPublisher } from './l2-block-publisher.js'; export { L2BlockPublisher } from './l2-block-publisher.js'; +export { PublisherConfig } from './config.js'; -export function getL2BlockPublisher(config: Config): L2BlockPublisher { - return new L2BlockPublisher(new AztecEthereumjsTxSender(config)); +export function getL2BlockPublisher(config: PublisherConfig & TxSenderConfig): L2BlockPublisher { + return new L2BlockPublisher(new EthereumjsTxSender(config), config); } diff --git a/yarn-project/sequencer-client/src/publisher/l2-block-publisher.test.ts b/yarn-project/sequencer-client/src/publisher/l2-block-publisher.test.ts index 28eb8ae006f3..4339cd7a9f04 100644 --- a/yarn-project/sequencer-client/src/publisher/l2-block-publisher.test.ts +++ b/yarn-project/sequencer-client/src/publisher/l2-block-publisher.test.ts @@ -24,7 +24,7 @@ describe('L2BlockPublisher', () => { txSender.sendTransaction.mockResolvedValueOnce(txHash); txSender.getTransactionReceipt.mockResolvedValueOnce(txReceipt); - publisher = new L2BlockPublisher(txSender, { sleepTimeMs: 1 }); + publisher = new L2BlockPublisher(txSender, { retryIntervalMs: 1 }); }); it('publishes l2 block to l1', async () => { diff --git a/yarn-project/sequencer-client/src/publisher/l2-block-publisher.ts b/yarn-project/sequencer-client/src/publisher/l2-block-publisher.ts index cae144d5295d..7767ce6464cc 100644 --- a/yarn-project/sequencer-client/src/publisher/l2-block-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l2-block-publisher.ts @@ -1,8 +1,7 @@ import { L2Block } from '@aztec/archiver'; +import { createDebugLogger, InterruptableSleep } from '@aztec/foundation'; import { L2BlockReceiver } from '../receiver.js'; - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const MIN_FEE_DISTRIBUTOR_BALANCE = 5n * 10n ** 17n; +import { PublisherConfig } from './config.js'; /** * Component responsible of pushing the txs to the chain and waiting for completion. @@ -22,21 +21,20 @@ export type L1ProcessRollupArgs = { /** * Publishes L2 blocks to the L1 rollup contracts. This implementation does *not* retry a transaction in - * the event of network congestion. + * the event of network congestion, but should work for local development. * - If sending (not mining) a tx fails, it retries indefinitely at 1-minute intervals. * - If the tx is not mined, keeps polling indefinitely at 1-second intervals. * * Adapted from https://github.com/AztecProtocol/aztec2-internal/blob/master/falafel/src/rollup_publisher.ts. */ export class L2BlockPublisher implements L2BlockReceiver { - private interrupted = false; - private interruptPromise = Promise.resolve(); - private interruptResolve = () => {}; + private interruptableSleep = new InterruptableSleep(); private sleepTimeMs: number; + private interrupted = false; + private log = createDebugLogger('aztec:sequencer'); - constructor(private txSender: PublisherTxSender, opts?: { sleepTimeMs?: number }) { - this.interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); - this.sleepTimeMs = opts?.sleepTimeMs ?? 60_000; + constructor(private txSender: PublisherTxSender, config?: PublisherConfig) { + this.sleepTimeMs = config?.retryIntervalMs ?? 60_000; } /** @@ -46,10 +44,11 @@ export class L2BlockPublisher implements L2BlockReceiver { public async processL2Block(l2BlockData: L2Block): Promise { const proof = Buffer.alloc(0); const txData = { proof, inputs: l2BlockData.encode() }; + //this.log(`Publishing L2 block: ${l2BlockData.inspect()}`); while (!this.interrupted) { if (!(await this.checkFeeDistributorBalance())) { - console.log(`Fee distributor ETH balance too low, awaiting top up...`); + this.log(`Fee distributor ETH balance too low, awaiting top up...`); await this.sleepOrInterrupted(); continue; } @@ -65,15 +64,15 @@ export class L2BlockPublisher implements L2BlockReceiver { // Check if someone else moved the block id if (!(await this.checkNextL2BlockId(l2BlockData.number))) { - console.log('Publish failed. Contract changed underfoot.'); + this.log('Publish failed. Contract changed underfoot.'); break; } - console.log(`Transaction status failed: ${receipt.transactionHash}`); + this.log(`Transaction status failed: ${receipt.transactionHash}`); await this.sleepOrInterrupted(); } - console.log('Publish rollup interrupted.'); + this.log('Publish rollup interrupted.'); return false; } @@ -85,7 +84,7 @@ export class L2BlockPublisher implements L2BlockReceiver { */ public interrupt() { this.interrupted = true; - this.interruptResolve(); + this.interruptableSleep.interrupt(); } // TODO: Check fee distributor has at least 0.5 ETH. @@ -105,7 +104,7 @@ export class L2BlockPublisher implements L2BlockReceiver { try { return await this.txSender.sendTransaction(encodedData); } catch (err) { - console.log(`Error sending tx to L1`, err); + this.log(`Error sending tx to L1`, err); await this.sleepOrInterrupted(); } } @@ -118,14 +117,13 @@ export class L2BlockPublisher implements L2BlockReceiver { try { return await this.txSender.getTransactionReceipt(txHash); } catch (err) { - console.log(`Error getting tx receipt`, err); + this.log(`Error getting tx receipt`, err); await this.sleepOrInterrupted(); } } } protected async sleepOrInterrupted() { - const ms = this.sleepTimeMs; - await Promise.race([new Promise(resolve => setTimeout(resolve, ms)), this.interruptPromise]); + await this.interruptableSleep.sleep(this.sleepTimeMs); } } diff --git a/yarn-project/sequencer-client/src/sequencer/block_builder.ts b/yarn-project/sequencer-client/src/sequencer/block_builder.ts new file mode 100644 index 000000000000..ec4315f596fd --- /dev/null +++ b/yarn-project/sequencer-client/src/sequencer/block_builder.ts @@ -0,0 +1,137 @@ +import { ContractData, L2Block } from '@aztec/archiver'; +import { + Fr, + KERNEL_NEW_CONTRACTS_LENGTH, + KERNEL_NEW_COMMITMENTS_LENGTH, + KERNEL_NEW_NULLIFIERS_LENGTH, + AppendOnlyTreeSnapshot, + NewContractData, +} from '@aztec/circuits.js'; +import { MerkleTreeId, MerkleTreeOperations } from '@aztec/world-state'; +import { Tx } from '@aztec/p2p'; + +const mapContractData = (n: NewContractData) => { + const contractData = new ContractData(n.contractAddress, n.portalContractAddress); + return contractData; +}; + +export class BlockBuilder { + private dataTreeLeaves: Buffer[] = []; + private nullifierTreeLeaves: Buffer[] = []; + private contractTreeLeaves: Buffer[] = []; + + constructor(private db: MerkleTreeOperations, private nextRollupId: number, private tx: Tx) { + this.dataTreeLeaves = tx.data.end.newCommitments.map((x: Fr) => x.toBuffer()); + this.nullifierTreeLeaves = tx.data.end.newNullifiers.map((x: Fr) => x.toBuffer()); + this.contractTreeLeaves = tx.data.end.newContracts.map((x: NewContractData) => x.functionTreeRoot.toBuffer()); + } + + public async buildL2Block() { + const startPrivateDataTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.DATA_TREE); + const startNullifierTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); + const startContractTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + const startTreeOfHistoricPrivateDataTreeRootsSnapshot = await this.getTreeSnapshot( + MerkleTreeId.DATA_TREE_ROOTS_TREE, + ); + const startTreeOfHistoricContractTreeRootsSnapshot = await this.getTreeSnapshot( + MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, + ); + + await this.updateTrees(); + + const endPrivateDataTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.DATA_TREE); + const endNullifierTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE); + const endContractTreeSnapshot = await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + const endTreeOfHistoricPrivateDataTreeRootsSnapshot = await this.getTreeSnapshot(MerkleTreeId.DATA_TREE_ROOTS_TREE); + const endTreeOfHistoricContractTreeRootsSnapshot = await this.getTreeSnapshot( + MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, + ); + + const l2block = L2Block.fromFields({ + number: this.nextRollupId, + startPrivateDataTreeSnapshot, + endPrivateDataTreeSnapshot, + startNullifierTreeSnapshot, + endNullifierTreeSnapshot, + startContractTreeSnapshot, + endContractTreeSnapshot, + startTreeOfHistoricPrivateDataTreeRootsSnapshot, + endTreeOfHistoricPrivateDataTreeRootsSnapshot, + startTreeOfHistoricContractTreeRootsSnapshot, + endTreeOfHistoricContractTreeRootsSnapshot, + newCommitments: this.dataTreeLeaves.map(b => new Fr(b)), + newNullifiers: this.nullifierTreeLeaves.map(b => new Fr(b)), + newContracts: this.contractTreeLeaves.map(b => new Fr(b)), + newContractData: this.tx.data.end.newContracts.map(mapContractData), + }); + return l2block; + } + + private async getTreeSnapshot(id: MerkleTreeId): Promise { + const treeInfo = await this.db.getTreeInfo(id); + return new AppendOnlyTreeSnapshot(new Fr(treeInfo.root), Number(treeInfo.size)); + } + + private async updateTrees() { + for (let i = 0; i < KERNEL_NEW_COMMITMENTS_LENGTH; i++) { + await this.db.appendLeaves(MerkleTreeId.DATA_TREE, [this.dataTreeLeaves[i]]); + } + for (let i = 0; i < KERNEL_NEW_NULLIFIERS_LENGTH; i++) { + await this.db.appendLeaves(MerkleTreeId.NULLIFIER_TREE, [this.nullifierTreeLeaves[i]]); + } + for (let i = 0; i < KERNEL_NEW_CONTRACTS_LENGTH; i++) { + await this.db.appendLeaves(MerkleTreeId.CONTRACT_TREE, [this.contractTreeLeaves[i]]); + } + const newDataTreeInfo = await this.getTreeSnapshot(MerkleTreeId.DATA_TREE); + const newContractsTreeInfo = await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE); + await this.db.appendLeaves(MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, [newContractsTreeInfo.root.toBuffer()]); + await this.db.appendLeaves(MerkleTreeId.DATA_TREE_ROOTS_TREE, [newDataTreeInfo.root.toBuffer()]); + } + + // private async getCurrentTreeRoots() { + // return await Promise.all([ + // this.getTreeRoot(MerkleTreeId.NULLIFIER_TREE), + // this.getTreeRoot(MerkleTreeId.CONTRACT_TREE), + // ]); + // } + + // private getTxContext(tx: Tx) { + // if (tx.data.end.newContracts.length !== 1) { + // throw new Error(`Only txs that deploy exactly one contract are supported for now`); + // } + // const [newContract] = tx.data.end.newContracts; + + // return new TxContext( + // false, // isFeePayment + // false, // isRebatePayment + // true, // isContractDeployment + // new ContractDeploymentData( + // TODO_FR, // TODO: constructorVkHash + // newContract.functionTreeRoot, + // TODO_FR, // TODO: contractAddressSalt + // newContract.portalContractAddress, + // ), + // ); + // } + + // private getKernelDataFor(tx: Tx) { + // return new PreviousKernelData( + // tx.data, + // TODO, // TODO: proof, isn't this the tx.data.end.aggregationObject?, + // TODO, // TODO: vk + // TODO_NUM, // TODO: vkIndex + // Array(VK_TREE_HEIGHT).fill(TODO_FR), // TODO: vkSiblingPath + // ); + // } + + // private getConstantBaseRollupData(): Promise { + // throw new Error('Unimplemented'); + // } + + // private async getBaseRollupInputsFor(tx: Tx) { + // return BaseRollupInputs.from({ + // proverId: TODO_FR, + // constants: await this.getConstantBaseRollupData(), + // } as any); // TODO: Carry on... + // } +} diff --git a/yarn-project/sequencer-client/src/sequencer/config.ts b/yarn-project/sequencer-client/src/sequencer/config.ts new file mode 100644 index 000000000000..07f1554bd1ca --- /dev/null +++ b/yarn-project/sequencer-client/src/sequencer/config.ts @@ -0,0 +1,9 @@ +/** + * The sequencer configuration. + */ +export interface SequencerConfig { + /** + * The number of ms to wait between polling for pending txs. + */ + transactionPollingInterval: number; +} diff --git a/yarn-project/sequencer-client/src/sequencer/index.ts b/yarn-project/sequencer-client/src/sequencer/index.ts new file mode 100644 index 000000000000..46d380e03dd5 --- /dev/null +++ b/yarn-project/sequencer-client/src/sequencer/index.ts @@ -0,0 +1,127 @@ +import { P2P, Tx } from '@aztec/p2p'; +import { WorldStateSynchroniser, WorldStateStatus } from '@aztec/world-state'; +import { RunningPromise } from '../deps/running_promise.js'; +import { L2BlockPublisher } from '../publisher/l2-block-publisher.js'; +import { createDebugLogger } from '@aztec/foundation'; +import { BlockBuilder } from './block_builder.js'; +import { SequencerConfig } from './config.js'; + +/** + * Sequencer client + * - Wins a period of time to become the sequencer (depending on finalised protocol). + * - Chooses a set of txs from the tx pool to be in the rollup. + * - Simulate the rollup of txs. + * - Adds proof requests to the request pool (not for this milestone). + * - Receives results to those proofs from the network (repeats as necessary) (not for this milestone). + * - Publishes L1 tx(s) to the rollup contract via RollupPublisher. + * - For this milestone, the sequencer will just simulate and publish a 1x1 rollup and publish it to L1. + */ +export class Sequencer { + private runningPromise?: RunningPromise; + private pollingIntervalMs: number; + private lastBlockNumber = -1; + private state = SequencerState.STOPPED; + + constructor( + private publisher: L2BlockPublisher, + private p2pClient: P2P, + private worldState: WorldStateSynchroniser, + config?: SequencerConfig, + private log = createDebugLogger('aztec:sequencer'), + ) { + this.pollingIntervalMs = config?.transactionPollingInterval ?? 1_000; + } + + public async start() { + // TODO: Should we wait for worldstate to be ready, or is the caller expected to run await start? + this.lastBlockNumber = await this.worldState.status().then((s: WorldStateStatus) => s.syncedToL2Block); + + this.runningPromise = new RunningPromise(this.work.bind(this), { pollingInterval: this.pollingIntervalMs }); + this.runningPromise.start(); + this.state = SequencerState.IDLE; + } + + public async stop(): Promise { + await this.runningPromise?.stop(); + this.publisher.interrupt(); + this.state = SequencerState.STOPPED; + this.log('Stopped sequencer'); + } + + public status() { + return { state: this.state }; + } + + /** + * Grabs a single tx from the p2p client, constructs a block, and pushes it to L1. + */ + protected async work() { + try { + // Update state when the previous block has been synched + const prevBlockSynched = await this.isBlockSynched(); + if (prevBlockSynched && this.state === SequencerState.PUBLISHING_BLOCK) { + this.log(`Block has been synched`); + this.state = SequencerState.IDLE; + } + + // Do not go forward with new block if the previous one has not been mined and processed + if (!prevBlockSynched) { + return; + } + + this.state = SequencerState.WAITING_FOR_TXS; + + // Get a single tx (for now) to build the new block + // P2P client is responsible for ensuring this tx is eligible (proof ok, not mined yet, etc) + const [tx] = await this.p2pClient.getTxs(); + if (!tx) { + this.log(`No txs in the mempool for a new block`); + return; + } else { + this.log(`Processing tx ${tx.txId.toString('hex')}`); + } + + this.state = SequencerState.CREATING_BLOCK; + + // Build the new block by running the rollup circuits + const block = await this.buildBlock(tx); + this.log(`Assembled block ${block.number}`); + + // Publishes new block to the network and awaits the tx to be mined + this.state = SequencerState.PUBLISHING_BLOCK; + const published = await this.publisher.processL2Block(block); + if (published) { + this.log(`Successfully published block ${block.number}`); + this.lastBlockNumber++; + } else { + this.log(`Failed to publish block`); + } + } catch (err) { + this.log(`Error doing work: ${err}`, 'error'); + } + } + + /** + * Returns whether the previous block sent has been mined, and all dependencies have caught up with it. + * @returns Boolean indicating if our dependencies are synched to the latest block. + */ + protected async isBlockSynched() { + return ( + (await this.worldState.status().then((s: WorldStateStatus) => s.syncedToL2Block)) >= this.lastBlockNumber && + (await this.p2pClient.getStatus().then(s => s.syncedToL2Block)) >= this.lastBlockNumber + ); + } + + protected async buildBlock(tx: Tx) { + const blockBuilder = new BlockBuilder(this.worldState, this.lastBlockNumber + 1, tx); + return await blockBuilder.buildL2Block(); + } +} + +export enum SequencerState { + IDLE, + WAITING_FOR_TXS, + CREATING_BLOCK, + PUBLISHING_BLOCK, + STOPPED, +} diff --git a/yarn-project/sequencer-client/test/l2-block-publisher.test.ts b/yarn-project/sequencer-client/test/l2-block-publisher.test.ts index eff87471472d..80b43d7db442 100644 --- a/yarn-project/sequencer-client/test/l2-block-publisher.test.ts +++ b/yarn-project/sequencer-client/test/l2-block-publisher.test.ts @@ -4,7 +4,7 @@ import { EthereumRpc } from '@aztec/ethereum.js/eth_rpc'; import { WalletProvider } from '@aztec/ethereum.js/provider'; import { Rollup } from '@aztec/l1-contracts'; import { beforeAll, describe, expect, it } from '@jest/globals'; -import { AztecEthereumjsTxSender } from '../src/publisher/aztec-ethereumjs-tx-sender.js'; +import { EthereumjsTxSender } from '../src/publisher/ethereumjs-tx-sender.js'; import { L2BlockPublisher } from '../src/publisher/l2-block-publisher.js'; import { hexStringToBuffer } from '../src/utils.js'; @@ -21,19 +21,17 @@ describe('L2BlockPublisher integration', () => { let l2Proof: Buffer; beforeAll(async () => { - let deployer: EthAddress; - ({ ethRpc, rollup, deployer } = await deployRollup()); + ({ ethRpc, rollup } = await deployRollup()); l2Block = mockRandomL2Block(42); l2Proof = Buffer.alloc(0); publisher = new L2BlockPublisher( - new AztecEthereumjsTxSender({ + new EthereumjsTxSender({ ethereumHost: anvilHost, - feeDistributor: deployer.toChecksumString(), requiredConfirmations: 1, - rollupContract: rollup.address.toChecksumString(), - sequencerPrivateKey: sequencerPK + rollupContract: rollup.address, + sequencerPrivateKey: hexStringToBuffer(sequencerPK) }), { sleepTimeMs: 100 @@ -45,12 +43,12 @@ describe('L2BlockPublisher integration', () => { const blockNumber = await ethRpc.blockNumber(); await publisher.processL2Block(l2Block); - const logs = await rollup.getLogs('RollupBlockProcessed', { fromBlock: blockNumber }); + const logs = await rollup.getLogs('L2BlockProcessed', { fromBlock: blockNumber }); expect(logs).toHaveLength(1); - expect(logs[0].args.rollupBlockNumber).toEqual(42n); + expect(logs[0].args.blockNum).toEqual(42n); const tx = await ethRpc.getTransactionByHash(logs[0].transactionHash!); - const expectedData = rollup.methods.processRollup(l2Proof, l2Block.encode()).encodeABI(); + const expectedData = rollup.methods.process(l2Proof, l2Block.encode()).encodeABI(); expect(tx.input).toEqual(expectedData); }); }); diff --git a/yarn-project/sequencer-client/tsconfig.dest.json b/yarn-project/sequencer-client/tsconfig.dest.json index 965aaa1c433e..965ace853b3b 100644 --- a/yarn-project/sequencer-client/tsconfig.dest.json +++ b/yarn-project/sequencer-client/tsconfig.dest.json @@ -1,4 +1,12 @@ { "extends": ".", - "exclude": ["**/*.test.*", "**/fixtures/*"] + "exclude": ["**/*.test.*", "**/fixtures/*"], + "references": [ + { "path": "../archiver/tsconfig.dest.json" }, + { "path": "../circuits.js/tsconfig.dest.json" }, + { "path": "../l1-contracts/tsconfig.dest.json" }, + { "path": "../merkle-tree/tsconfig.dest.json" }, + { "path": "../p2p/tsconfig.dest.json" }, + { "path": "../world-state/tsconfig.dest.json" } + ] } diff --git a/yarn-project/sequencer-client/tsconfig.json b/yarn-project/sequencer-client/tsconfig.json index dec34639a4a9..c6270da2f41c 100644 --- a/yarn-project/sequencer-client/tsconfig.json +++ b/yarn-project/sequencer-client/tsconfig.json @@ -5,5 +5,13 @@ "rootDir": "src", "tsBuildInfoFile": ".tsbuildinfo" }, - "include": ["src", "test"] + "include": ["src", "test"], + "references": [ + { "path": "../archiver/tsconfig.dest.json" }, + { "path": "../circuits.js/tsconfig.dest.json" }, + { "path": "../l1-contracts/tsconfig.dest.json" }, + { "path": "../merkle-tree/tsconfig.dest.json" }, + { "path": "../p2p/tsconfig.dest.json" }, + { "path": "../world-state/tsconfig.dest.json" } + ] } diff --git a/yarn-project/world-state/package.json b/yarn-project/world-state/package.json index 2cb91fcb8e81..59f29ab73e38 100644 --- a/yarn-project/world-state/package.json +++ b/yarn-project/world-state/package.json @@ -8,6 +8,7 @@ "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", + "formatting:fix": "run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" }, "jest": { @@ -25,6 +26,7 @@ }, "dependencies": { "@aztec/archiver": "workspace:^", + "@aztec/circuits.js": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/merkle-tree": "workspace:^", "levelup": "^5.1.1", diff --git a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts index f84409a894ca..0111f8ff0214 100644 --- a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts +++ b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.test.ts @@ -1,9 +1,11 @@ import { ServerWorldStateSynchroniser } from './server_world_state_synchroniser.js'; -import { L2BlockSource, L2BlockSourceSyncStatus, L2Block } from '@aztec/archiver'; +import { L2BlockSource, L2Block, ContractData } from '@aztec/archiver'; import { WorldStateRunningState } from './world_state_synchroniser.js'; -import { Pedersen, MerkleTreeDb, MerkleTreeId, SiblingPath, StandardMerkleTree } from '@aztec/merkle-tree'; -import { sleep } from '@aztec/foundation'; +import { Pedersen, SiblingPath, StandardMerkleTree } from '@aztec/merkle-tree'; +import { randomBytes, sleep } from '@aztec/foundation'; import { jest } from '@jest/globals'; +import { AppendOnlyTreeSnapshot, EthAddress, Fr } from '@aztec/circuits.js'; +import { MerkleTreeDb, MerkleTreeId } from '../index.js'; /** * Generic mock implementation. @@ -12,11 +14,6 @@ type Mockify = { [P in keyof T]: jest.Mock; }; -const syncStatus = { - syncedToBlock: 0, - latestBlock: 0, -} as L2BlockSourceSyncStatus; - const LATEST_BLOCK_NUMBER = 5; const getLatestBlockNumber = () => LATEST_BLOCK_NUMBER; let nextBlocks: L2Block[] = []; @@ -26,21 +23,41 @@ const consumeNextBlocks = () => { return Promise.resolve(blocks); }; +const getMockTreeSnapshot = () => { + return new AppendOnlyTreeSnapshot(new Fr(randomBytes(32)), 16); +}; + +const getMockContractData = () => { + return new ContractData(new Fr(randomBytes(32)), new EthAddress(randomBytes(20))); +}; + const getMockBlock = (blockNumber: number, newContractsCommitments?: Buffer[]) => { - const block = { - number: blockNumber, - newContracts: newContractsCommitments ?? [Buffer.alloc(32, 0)], - } as L2Block; + const block = new L2Block( + blockNumber, + getMockTreeSnapshot(), + getMockTreeSnapshot(), + getMockTreeSnapshot(), + getMockTreeSnapshot(), + getMockTreeSnapshot(), + getMockTreeSnapshot(), + getMockTreeSnapshot(), + getMockTreeSnapshot(), + getMockTreeSnapshot(), + getMockTreeSnapshot(), + [new Fr(randomBytes(32))], + [new Fr(randomBytes(32))], + newContractsCommitments?.map(x => new Fr(x)) ?? [new Fr(randomBytes(32))], + [getMockContractData()], + ); return block; }; const createSynchroniser = (merkleTreeDb: any, rollupSource: any) => - new ServerWorldStateSynchroniser(merkleTreeDb as MerkleTreeDb, rollupSource as L2BlockSource, 1, 100); + new ServerWorldStateSynchroniser(merkleTreeDb as MerkleTreeDb, rollupSource as L2BlockSource); describe('server_world_state_synchroniser', () => { const pedersen: Pedersen = new Pedersen(); const rollupSource: Mockify = { - getSyncStatus: jest.fn().mockImplementation(() => Promise.resolve(syncStatus)), getLatestBlockNum: jest.fn().mockImplementation(getLatestBlockNumber), getL2Blocks: jest.fn().mockImplementation(consumeNextBlocks), } as any; @@ -68,15 +85,15 @@ describe('server_world_state_synchroniser', () => { // test initial state let status = await server.status(); - expect(status.syncedToL2Block).toEqual(-1); + expect(status.syncedToL2Block).toEqual(0); expect(status.state).toEqual(WorldStateRunningState.IDLE); // create an initial block - let currentBlockNumber = -1; + let currentBlockNumber = 0; nextBlocks = [getMockBlock(currentBlockNumber + 1)]; // start the sync process but don't await - server.start(0).catch(() => console.log('Sync not completed!!')); + server.start().catch(() => console.log('Sync not completed!!')); // now setup a loop to monitor the sync progress and push new blocks in while (currentBlockNumber <= LATEST_BLOCK_NUMBER) { @@ -114,7 +131,7 @@ describe('server_world_state_synchroniser', () => { it('enables blocking until synced', async () => { const server = createSynchroniser(merkleTreeDb, rollupSource); - let currentBlockNumber = -1; + let currentBlockNumber = 0; const newBlocks = async () => { while (currentBlockNumber <= LATEST_BLOCK_NUMBER) { @@ -127,7 +144,7 @@ describe('server_world_state_synchroniser', () => { const newBlockPromise = newBlocks(); // kick off the synching - const syncPromise = server.start(0); + const syncPromise = server.start(); // await the synching await syncPromise; @@ -145,7 +162,7 @@ describe('server_world_state_synchroniser', () => { it('handles multiple calls to start', async () => { const server = createSynchroniser(merkleTreeDb, rollupSource); - let currentBlockNumber = -1; + let currentBlockNumber = 0; const newBlocks = async () => { while (currentBlockNumber < LATEST_BLOCK_NUMBER) { @@ -159,10 +176,10 @@ describe('server_world_state_synchroniser', () => { const newBlockPromise = newBlocks(); // kick off the synching - await server.start(0); + await server.start(); // call start again, should get back the same promise - await server.start(0); + await server.start(); // wait until the block production has finished await newBlockPromise; @@ -172,24 +189,30 @@ describe('server_world_state_synchroniser', () => { it('immediately syncs if no new blocks', async () => { const server = createSynchroniser(merkleTreeDb, rollupSource); + rollupSource.getLatestBlockNum.mockImplementationOnce(() => { + return Promise.resolve(0); + }); // kick off the synching - const syncPromise = server.start(5); + const syncPromise = server.start(); // it should already be synced, no need to push new blocks await syncPromise; const status = await server.status(); expect(status.state).toBe(WorldStateRunningState.RUNNING); - expect(status.syncedToL2Block).toBe(LATEST_BLOCK_NUMBER); + expect(status.syncedToL2Block).toBe(0); await server.stop(); }); it("can't be started if already stopped", async () => { const server = createSynchroniser(merkleTreeDb, rollupSource); + rollupSource.getLatestBlockNum.mockImplementationOnce(() => { + return Promise.resolve(0); + }); // kick off the synching - const syncPromise = server.start(5); + const syncPromise = server.start(); await syncPromise; await server.stop(); @@ -204,11 +227,20 @@ describe('server_world_state_synchroniser', () => { .fill(0) .map((_, index) => getMockBlock(index, [Buffer.alloc(32, index)])); // sync the server - await server.start(0); - expect(merkleTreeDb.appendLeaves).toHaveBeenCalledTimes(totalBlocks); + await server.start(); + // there are 5 trees updated + expect(merkleTreeDb.appendLeaves).toHaveBeenCalledTimes(totalBlocks * 5); + // there should be a call to append to the contract tree for each block for (let i = 0; i < totalBlocks; i++) { - expect(merkleTreeDb.appendLeaves.mock.calls[i][0]).toEqual(MerkleTreeId.CONTRACT_TREE); - expect(merkleTreeDb.appendLeaves.mock.calls[i][1]).toEqual([Buffer.alloc(32, i)]); + expect( + merkleTreeDb.appendLeaves.mock.calls.findIndex(call => { + if (call[0] !== MerkleTreeId.CONTRACT_TREE) { + return false; + } + const leaves = call[1] as Buffer[]; + return leaves.length === 1 && leaves[0].equals(Buffer.alloc(32, i)); + }), + ).not.toBe(-1); } await server.stop(); }); diff --git a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.ts b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.ts index 5179d239f58a..2c96ce32b82d 100644 --- a/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.ts +++ b/yarn-project/world-state/src/synchroniser/server_world_state_synchroniser.ts @@ -1,7 +1,8 @@ import { WorldStateRunningState, WorldStateStatus, WorldStateSynchroniser } from './world_state_synchroniser.js'; -import { MerkleTreeDb, MerkleTreeId } from '@aztec/merkle-tree'; import { L2BlockSource, L2BlockDownloader, L2Block } from '@aztec/archiver'; import { createDebugLogger } from '@aztec/foundation'; +import { MerkleTreeDb, MerkleTreeId, TreeInfo } from '../index.js'; +import { SiblingPath } from '@aztec/merkle-tree'; /** * Synchronises the world state with the L2 blocks from a L2BlockSource. @@ -9,8 +10,8 @@ import { createDebugLogger } from '@aztec/foundation'; * tree. */ export class ServerWorldStateSynchroniser implements WorldStateSynchroniser { - private currentL2BlockNum = -1; - private latestBlockNumberAtStart = -1; + private currentL2BlockNum = 0; + private latestBlockNumberAtStart = 0; private l2BlockDownloader: L2BlockDownloader; private syncPromise: Promise = Promise.resolve(); private syncResolve?: () => void = undefined; @@ -21,19 +22,16 @@ export class ServerWorldStateSynchroniser implements WorldStateSynchroniser { constructor( private merkleTreeDb: MerkleTreeDb, private l2BlockSource: L2BlockSource, - maxQueueSize = 1000, - pollIntervalMS = 10000, private log = createDebugLogger('aztec:world_state'), ) { - this.l2BlockDownloader = new L2BlockDownloader(l2BlockSource, maxQueueSize, pollIntervalMS); + this.l2BlockDownloader = new L2BlockDownloader(l2BlockSource, 1000, 100); } /** * Starts the synchroniser. - * @param from - The block number to start downloading from. Defaults to 0. * @returns A promise that resolves once the initial sync is completed. */ - public async start(from = 0) { + public async start() { if (this.currentState === WorldStateRunningState.STOPPED) { throw new Error('Synchroniser already stopped'); } @@ -44,19 +42,20 @@ export class ServerWorldStateSynchroniser implements WorldStateSynchroniser { // get the current latest block number this.latestBlockNumberAtStart = await this.l2BlockSource.getLatestBlockNum(); + const blockToDownloadFrom = this.currentL2BlockNum + 1; + // if there are blocks to be retrieved, go to a synching state - if (from < this.latestBlockNumberAtStart) { + if (blockToDownloadFrom <= this.latestBlockNumberAtStart) { this.setCurrentState(WorldStateRunningState.SYNCHING); this.syncPromise = new Promise(resolve => { this.syncResolve = resolve; }); - this.log(`starting sync from ${from}, latest block ${this.latestBlockNumberAtStart}`); + this.log(`Starting sync from ${blockToDownloadFrom}, latest block ${this.latestBlockNumberAtStart}`); } else { // if no blocks to be retrieved, go straight to running this.setCurrentState(WorldStateRunningState.RUNNING); - this.currentL2BlockNum = this.latestBlockNumberAtStart; this.syncPromise = Promise.resolve(); - this.log(`already synched to latest block at ${this.latestBlockNumberAtStart}`); + this.log(`Next block ${blockToDownloadFrom} already beyond latest block at ${this.latestBlockNumberAtStart}`); } // start looking for further blocks @@ -67,8 +66,8 @@ export class ServerWorldStateSynchroniser implements WorldStateSynchroniser { } }; this.runningPromise = blockProcess(); - this.l2BlockDownloader.start(from); - this.log(`started block downloader from block ${from}`); + this.l2BlockDownloader.start(blockToDownloadFrom); + this.log(`Started block downloader from block ${blockToDownloadFrom}`); return this.syncPromise; } @@ -76,7 +75,7 @@ export class ServerWorldStateSynchroniser implements WorldStateSynchroniser { * Stops the synchroniser. */ public async stop() { - this.log('stopping world state...'); + this.log('Stopping world state...'); this.stopping = true; await this.l2BlockDownloader.stop(); await this.runningPromise; @@ -95,6 +94,35 @@ export class ServerWorldStateSynchroniser implements WorldStateSynchroniser { return Promise.resolve(status); } + /** + * Gets the tree info for the specified tree. + * @param treeId - Id of the tree to get information from. + * @returns The tree info for the specified tree. + */ + public async getTreeInfo(treeId: MerkleTreeId): Promise { + return await this.merkleTreeDb.getTreeInfo(treeId); + } + + /** + * Gets the sibling path for a leaf in a tree. + * @param treeId - The ID of the tree. + * @param index - The index of the leaf. + * @returns The sibling path for the leaf. + */ + public async getSiblingPath(treeId: MerkleTreeId, index: bigint): Promise { + return await this.merkleTreeDb.getSiblingPath(treeId, index); + } + + /** + * Appends leaves to a tree. + * @param treeId - The ID of the tree. + * @param leaves - The leaves to append. + * @returns Empty promise. + */ + public async appendLeaves(treeId: MerkleTreeId, leaves: Buffer[]): Promise { + await this.merkleTreeDb.appendLeaves(treeId, leaves); + } + /** * Handles a list of L2 blocks (i.e. Inserts the new commitments into the merkle tree). * @param l2blocks - The L2 blocks to handle. @@ -110,10 +138,52 @@ export class ServerWorldStateSynchroniser implements WorldStateSynchroniser { * @param l2block - The L2 block to handle. */ private async handleL2Block(l2block: L2Block) { - this.log(`committing block ${l2block.number}`); - await this.merkleTreeDb.appendLeaves(MerkleTreeId.CONTRACT_TREE, l2block.newContracts); - await this.merkleTreeDb.commit(); - this.log(`committed block ${l2block.number} to world state`); + const compareRoot = async (root: Buffer, treeId: MerkleTreeId) => { + const treeInfo = await this.merkleTreeDb.getTreeInfo(treeId); + return treeInfo.root.equals(root); + }; + const rootChecks = await Promise.all([ + compareRoot(l2block.endContractTreeSnapshot.root.toBuffer(), MerkleTreeId.CONTRACT_TREE), + compareRoot(l2block.endNullifierTreeSnapshot.root.toBuffer(), MerkleTreeId.NULLIFIER_TREE), + compareRoot(l2block.endPrivateDataTreeSnapshot.root.toBuffer(), MerkleTreeId.DATA_TREE), + compareRoot( + l2block.endTreeOfHistoricContractTreeRootsSnapshot.root.toBuffer(), + MerkleTreeId.CONTRACT_TREE_ROOTS_TREE, + ), + compareRoot( + l2block.endTreeOfHistoricPrivateDataTreeRootsSnapshot.root.toBuffer(), + MerkleTreeId.DATA_TREE_ROOTS_TREE, + ), + ]); + const ourBlock = rootChecks.every(x => x); + if (ourBlock) { + this.log(`Block ${l2block.number} is ours, committing world state..`); + await this.merkleTreeDb.commit(); + } else { + this.log(`Block ${l2block.number} is not ours, rolling back world state and committing state from chain..`); + await this.merkleTreeDb.rollback(); + + for (const [tree, leaves] of [ + [MerkleTreeId.CONTRACT_TREE, l2block.newContracts], + [MerkleTreeId.NULLIFIER_TREE, l2block.newNullifiers], + [MerkleTreeId.DATA_TREE, l2block.newCommitments], + ] as const) { + await this.merkleTreeDb.appendLeaves( + tree, + leaves.map(fr => fr.toBuffer()), + ); + } + + for (const [newTree, rootTree] of [ + [MerkleTreeId.DATA_TREE, MerkleTreeId.DATA_TREE_ROOTS_TREE], + [MerkleTreeId.CONTRACT_TREE, MerkleTreeId.CONTRACT_TREE_ROOTS_TREE], + ] as const) { + const newTreeInfo = await this.merkleTreeDb.getTreeInfo(newTree); + await this.merkleTreeDb.appendLeaves(rootTree, [newTreeInfo.root]); + } + + await this.merkleTreeDb.commit(); + } this.currentL2BlockNum = l2block.number; if ( this.currentState === WorldStateRunningState.SYNCHING && @@ -132,6 +202,6 @@ export class ServerWorldStateSynchroniser implements WorldStateSynchroniser { */ private setCurrentState(newState: WorldStateRunningState) { this.currentState = newState; - this.log(`moved to state ${WorldStateRunningState[this.currentState]}`); + this.log(`Moved to state ${WorldStateRunningState[this.currentState]}`); } } diff --git a/yarn-project/world-state/src/synchroniser/world_state_synchroniser.ts b/yarn-project/world-state/src/synchroniser/world_state_synchroniser.ts index 08b8c8079c19..3d06d2206f37 100644 --- a/yarn-project/world-state/src/synchroniser/world_state_synchroniser.ts +++ b/yarn-project/world-state/src/synchroniser/world_state_synchroniser.ts @@ -1,3 +1,5 @@ +import { MerkleTreeOperations } from '../index.js'; + /** * Defines the possible states of the world state synchroniser. */ @@ -25,7 +27,7 @@ export interface WorldStateStatus { /** * Defines the interface for a world state synchroniser. */ -export interface WorldStateSynchroniser { +export interface WorldStateSynchroniser extends MerkleTreeOperations { start(): void; status(): Promise; stop(): Promise; diff --git a/yarn-project/world-state/src/world-state-db/index.ts b/yarn-project/world-state/src/world-state-db/index.ts index bf39aac9eddc..e1520ecdf9d1 100644 --- a/yarn-project/world-state/src/world-state-db/index.ts +++ b/yarn-project/world-state/src/world-state-db/index.ts @@ -1,19 +1,26 @@ +import { SiblingPath } from '@aztec/merkle-tree'; + export * from './memory_world_state_db.js'; + /** - * Defines the possible tree IDs. + * Defines the possible Merkle tree IDs. */ -export enum WorldStateTreeId { +export enum MerkleTreeId { CONTRACT_TREE = 0, + CONTRACT_TREE_ROOTS_TREE = 1, + NULLIFIER_TREE = 2, + DATA_TREE = 3, + DATA_TREE_ROOTS_TREE = 4, } /** - * Defines tree information. + * Defines tree information. */ export interface TreeInfo { /** * The tree ID. */ - treeId: WorldStateTreeId; + treeId: MerkleTreeId; /** * The tree root. */ @@ -21,19 +28,22 @@ export interface TreeInfo { /** * The number of leaves in the tree. */ - size: number; + size: bigint; } /** - * Defines a batch update. + * Defines the interface for Merkle Tree operations. */ -export interface BatchUpdate { - /** - * The ID of a tree to be updated. - */ - treeId: WorldStateTreeId; - /** - * The leaves to be updated. - */ - elements: Buffer[]; +export interface MerkleTreeOperations { + getTreeInfo(treeId: MerkleTreeId): Promise; + appendLeaves(treeId: MerkleTreeId, leaves: Buffer[]): Promise; + getSiblingPath(treeId: MerkleTreeId, index: bigint): Promise; +} + +/** + * Defines the interface for a database that stores Merkle trees. + */ +export interface MerkleTreeDb extends MerkleTreeOperations { + commit(): Promise; + rollback(): Promise; } diff --git a/yarn-project/world-state/src/world-state-db/memory_world_state_db.ts b/yarn-project/world-state/src/world-state-db/memory_world_state_db.ts index c2aa0fa6aeaa..1cb75ff7a354 100644 --- a/yarn-project/world-state/src/world-state-db/memory_world_state_db.ts +++ b/yarn-project/world-state/src/world-state-db/memory_world_state_db.ts @@ -1,16 +1,14 @@ import { default as levelup } from 'levelup'; -import { - StandardMerkleTree, - Pedersen, - SiblingPath, - MerkleTreeDb, - MerkleTreeId, - TreeInfo, - IndexedTree, - MerkleTreeDepths, - MerkleTree, -} from '@aztec/merkle-tree'; +import { StandardMerkleTree, Pedersen, SiblingPath, IndexedTree, MerkleTree } from '@aztec/merkle-tree'; import { SerialQueue } from '@aztec/foundation'; +import { + CONTRACT_TREE_HEIGHT, + CONTRACT_TREE_ROOTS_TREE_HEIGHT, + NULLIFIER_TREE_HEIGHT, + PRIVATE_DATA_TREE_HEIGHT, + PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, +} from '@aztec/circuits.js'; +import { MerkleTreeDb, MerkleTreeId, TreeInfo } from './index.js'; /** * A convenience class for managing multiple merkle trees. @@ -30,21 +28,33 @@ export class MerkleTrees implements MerkleTreeDb { this.db, hasher, `${MerkleTreeId[MerkleTreeId.CONTRACT_TREE]}`, - MerkleTreeDepths.CONTRACT_TREE, + CONTRACT_TREE_HEIGHT, ); const contractTreeRootsTree = await StandardMerkleTree.new( this.db, hasher, `${MerkleTreeId[MerkleTreeId.CONTRACT_TREE_ROOTS_TREE]}`, - MerkleTreeDepths.CONTRACT_TREE_ROOTS_TREE, + CONTRACT_TREE_ROOTS_TREE_HEIGHT, ); const nullifierTree = await IndexedTree.new( this.db, hasher, `${MerkleTreeId[MerkleTreeId.NULLIFIER_TREE]}`, - MerkleTreeDepths.NULLIFIER_TREE, + NULLIFIER_TREE_HEIGHT, + ); + const dataTree = await StandardMerkleTree.new( + this.db, + hasher, + `${MerkleTreeId[MerkleTreeId.DATA_TREE]}`, + PRIVATE_DATA_TREE_HEIGHT, + ); + const dataTreeRootsTree = await StandardMerkleTree.new( + this.db, + hasher, + `${MerkleTreeId[MerkleTreeId.DATA_TREE_ROOTS_TREE]}`, + PRIVATE_DATA_TREE_ROOTS_TREE_HEIGHT, ); - this.trees = [contractTree, contractTreeRootsTree, nullifierTree]; + this.trees = [contractTree, contractTreeRootsTree, nullifierTree, dataTree, dataTreeRootsTree]; this.jobQueue.start(); } diff --git a/yarn-project/world-state/tsconfig.dest.json b/yarn-project/world-state/tsconfig.dest.json index 93f9b9ecffc2..86129be472e7 100644 --- a/yarn-project/world-state/tsconfig.dest.json +++ b/yarn-project/world-state/tsconfig.dest.json @@ -9,6 +9,9 @@ }, { "path": "../foundation/tsconfig.dest.json" + }, + { + "path": "../circuits.js/tsconfig.dest.json" } ], "exclude": ["**/*.test.*", "**/fixtures/*"] diff --git a/yarn-project/world-state/tsconfig.json b/yarn-project/world-state/tsconfig.json index a3bf0b269ada..ce8e34da7f38 100644 --- a/yarn-project/world-state/tsconfig.json +++ b/yarn-project/world-state/tsconfig.json @@ -14,9 +14,10 @@ }, { "path": "../foundation/tsconfig.dest.json" + }, + { + "path": "../circuits.js/tsconfig.dest.json" } ], - "include": [ - "src" - ] + "include": ["src"] } diff --git a/yarn-project/yarn-project-base/Dockerfile b/yarn-project/yarn-project-base/Dockerfile index 329795a5982b..7fa07b4c1162 100644 --- a/yarn-project/yarn-project-base/Dockerfile +++ b/yarn-project/yarn-project-base/Dockerfile @@ -16,6 +16,7 @@ COPY acir-simulator/package.json acir-simulator/package.json COPY archiver/package.json archiver/package.json COPY aztec-cli/package.json aztec-cli/package.json COPY aztec-rpc/package.json aztec-rpc/package.json +COPY aztec-node/package.json aztec-node/package.json COPY aztec.js/package.json aztec.js/package.json COPY docs/package.json docs/package.json COPY end-to-end/package.json end-to-end/package.json @@ -29,18 +30,20 @@ COPY key-store/package.json key-store/package.json COPY merkle-tree/package.json merkle-tree/package.json COPY noir-contracts/package.json noir-contracts/package.json COPY l1-contracts/package.json l1-contracts/package.json +COPY circuits.js/package.json circuits.js/package.json COPY p2p/package.json p2p/package.json COPY prover-client/package.json prover-client/package.json -COPY aztec-node/package.json aztec-node/package.json COPY sequencer-client/package.json sequencer-client/package.json COPY world-state/package.json world-state/package.json COPY package.json tsconfig.json yarn.lock .yarnrc.yml ./ COPY .yarn .yarn +# bundled dependencies +COPY .yalc .yalc -# Although we're attempting to be "zero-install", in practice we still need to build arch specific packages. -RUN yarn --immutable # Build submodule packages that have their own yarn.lock. RUN cd foundation && yarn --immutable && cd .. +# Although we're attempting to be "zero-install", in practice we still need to build arch specific packages. +RUN yarn --immutable # If everything's worked properly, we should no longer need access to the network. RUN echo "enableNetwork: false" >> .yarnrc.yml @@ -59,4 +62,4 @@ cd .yarn/cache && \ mkdir -p /root/.yarn/berry/cache && \ for F in *; do \ [[ $F =~ (.*-) ]] && ln $F /root/.yarn/berry/cache/${BASH_REMATCH[1]}8.zip; \ -done' \ No newline at end of file +done' diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index b3fc4b684f8a..e8459c487468 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -38,16 +38,20 @@ __metadata: version: 0.0.0-use.local resolution: "@aztec/archiver@workspace:archiver" dependencies: + "@aztec/circuits.js": "workspace:^" "@aztec/ethereum.js": "workspace:^" "@aztec/foundation": "workspace:^" + "@aztec/l1-contracts": "workspace:^" "@jest/globals": ^29.5.0 "@rushstack/eslint-patch": ^1.2.0 "@types/debug": ^4.1.7 "@types/jest": ^29.4.1 "@types/node": ^18.15.2 "@types/ws": ^8.5.4 + concurrently: ^7.6.0 debug: ^4.3.4 jest: ^29.5.0 + jest-mock-extended: ^3.0.4 ts-jest: ^29.0.5 ts-node: ^10.9.1 tsc-watch: ^6.0.0 @@ -83,12 +87,16 @@ __metadata: dependencies: "@aztec/archiver": "workspace:^" "@aztec/ethereum.js": "workspace:^" + "@aztec/foundation": "workspace:^" + "@aztec/l1-contracts": "workspace:^" "@aztec/p2p": "workspace:^" + "@aztec/sequencer-client": "workspace:^" "@aztec/world-state": "workspace:^" "@jest/globals": ^29.4.3 "@rushstack/eslint-patch": ^1.1.4 "@types/jest": ^29.4.0 "@types/node": ^18.7.23 + concurrently: ^7.6.0 jest: ^28.1.3 ts-jest: ^28.0.7 ts-node: ^10.9.1 @@ -147,6 +155,31 @@ __metadata: languageName: unknown linkType: soft +"@aztec/circuits.js@workspace:^, @aztec/circuits.js@workspace:circuits.js": + version: 0.0.0-use.local + resolution: "@aztec/circuits.js@workspace:circuits.js" + dependencies: + "@aztec/foundation": "workspace:^" + "@aztec/wasm": "workspace:^" + "@jest/globals": ^29.4.3 + "@types/detect-node": ^2.0.0 + "@types/jest": ^29.4.0 + "@types/node": ^18.7.23 + "@typescript-eslint/eslint-plugin": ^5.54.1 + "@typescript-eslint/parser": ^5.54.1 + cross-fetch: ^3.1.5 + detect-node: ^2.1.0 + eslint: ^8.35.0 + jest: ^28.1.3 + prettier: ^2.8.4 + ts-dedent: ^2.2.0 + ts-jest: ^28.0.7 + ts-node: ^10.9.1 + tslib: ^2.4.0 + typescript: ^4.9.5 + languageName: unknown + linkType: soft + "@aztec/docs@workspace:docs": version: 0.0.0-use.local resolution: "@aztec/docs@workspace:docs" @@ -343,6 +376,7 @@ __metadata: resolution: "@aztec/p2p@workspace:p2p" dependencies: "@aztec/archiver": "workspace:^" + "@aztec/circuits.js": "workspace:^" "@aztec/foundation": "workspace:^" "@jest/globals": ^29.4.3 "@rushstack/eslint-patch": ^1.1.4 @@ -373,13 +407,17 @@ __metadata: languageName: unknown linkType: soft -"@aztec/sequencer-client@workspace:sequencer-client": +"@aztec/sequencer-client@workspace:^, @aztec/sequencer-client@workspace:sequencer-client": version: 0.0.0-use.local resolution: "@aztec/sequencer-client@workspace:sequencer-client" dependencies: "@aztec/archiver": "workspace:^" + "@aztec/circuits.js": "workspace:^" "@aztec/ethereum.js": "workspace:^" + "@aztec/foundation": "workspace:^" "@aztec/l1-contracts": "workspace:^" + "@aztec/p2p": "workspace:^" + "@aztec/world-state": "workspace:^" "@jest/globals": ^29.4.3 "@rushstack/eslint-patch": ^1.1.4 "@types/jest": ^29.4.0 @@ -394,11 +432,26 @@ __metadata: languageName: unknown linkType: soft +"@aztec/wasm@workspace:.yalc/@aztec/wasm, @aztec/wasm@workspace:^": + version: 0.0.0-use.local + resolution: "@aztec/wasm@workspace:.yalc/@aztec/wasm" + dependencies: + "@aztec/foundation": "workspace:^" + "@types/leveldown": ^4.0.3 + detect-node: ^2.1.0 + leveldown: ^6.1.1 + levelup: ^5.1.1 + memdown: ^6.1.1 + tslib: ^2.4.0 + languageName: unknown + linkType: soft + "@aztec/world-state@workspace:^, @aztec/world-state@workspace:world-state": version: 0.0.0-use.local resolution: "@aztec/world-state@workspace:world-state" dependencies: "@aztec/archiver": "workspace:^" + "@aztec/circuits.js": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/merkle-tree": "workspace:^" "@jest/globals": ^29.4.3 @@ -1910,6 +1963,16 @@ __metadata: languageName: node linkType: hard +"@types/leveldown@npm:^4.0.3": + version: 4.0.3 + resolution: "@types/leveldown@npm:4.0.3" + dependencies: + "@types/abstract-leveldown": "*" + "@types/node": "*" + checksum: 0a476bd8d3c71266fdb323875d3312bf7828d6ab9f1bf9882a0ff93d04044660e45cd211ca8ec34c5665eaa773f98fe9fee14235792835bd06cb68192fe44669 + languageName: node + linkType: hard + "@types/levelup@npm:^5.1.2": version: 5.1.2 resolution: "@types/levelup@npm:5.1.2" @@ -2006,7 +2069,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^5.38.0": +"@typescript-eslint/eslint-plugin@npm:^5.38.0, @typescript-eslint/eslint-plugin@npm:^5.54.1": version: 5.56.0 resolution: "@typescript-eslint/eslint-plugin@npm:5.56.0" dependencies: @@ -2030,7 +2093,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:^5.38.0": +"@typescript-eslint/parser@npm:^5.38.0, @typescript-eslint/parser@npm:^5.54.1": version: 5.56.0 resolution: "@typescript-eslint/parser@npm:5.56.0" dependencies: @@ -3284,7 +3347,7 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.21.0": +"eslint@npm:^8.21.0, eslint@npm:^8.35.0": version: 8.36.0 resolution: "eslint@npm:8.36.0" dependencies: @@ -4578,7 +4641,7 @@ __metadata: languageName: node linkType: hard -"jest-mock-extended@npm:^3.0.1, jest-mock-extended@npm:^3.0.3": +"jest-mock-extended@npm:^3.0.1, jest-mock-extended@npm:^3.0.3, jest-mock-extended@npm:^3.0.4": version: 3.0.4 resolution: "jest-mock-extended@npm:3.0.4" dependencies: @@ -5143,6 +5206,18 @@ __metadata: languageName: node linkType: hard +"leveldown@npm:^6.1.1": + version: 6.1.1 + resolution: "leveldown@npm:6.1.1" + dependencies: + abstract-leveldown: ^7.2.0 + napi-macros: ~2.0.0 + node-gyp: latest + node-gyp-build: ^4.3.0 + checksum: 00ba086f83c930683271aae35c89ce684bd31afcc4ba15912a071865f21d86000c48eb83b55ae554b6d328e0ba82a08868dd3b64abed750db89f38b8718c84af + languageName: node + linkType: hard + "levelup@npm:^5.1.1": version: 5.1.1 resolution: "levelup@npm:5.1.1" @@ -5529,6 +5604,13 @@ __metadata: languageName: node linkType: hard +"napi-macros@npm:~2.0.0": + version: 2.0.0 + resolution: "napi-macros@npm:2.0.0" + checksum: 30384819386977c1f82034757014163fa60ab3c5a538094f778d38788bebb52534966279956f796a92ea771c7f8ae072b975df65de910d051ffbdc927f62320c + languageName: node + linkType: hard + "natural-compare-lite@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare-lite@npm:1.4.0" @@ -5580,7 +5662,7 @@ __metadata: languageName: node linkType: hard -"node-gyp-build@npm:^4.2.0": +"node-gyp-build@npm:^4.2.0, node-gyp-build@npm:^4.3.0": version: 4.6.0 resolution: "node-gyp-build@npm:4.6.0" bin: @@ -5874,7 +5956,7 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^2.7.1": +"prettier@npm:^2.7.1, prettier@npm:^2.8.4": version: 2.8.6 resolution: "prettier@npm:2.8.6" bin: @@ -6587,6 +6669,13 @@ __metadata: languageName: node linkType: hard +"ts-dedent@npm:^2.2.0": + version: 2.2.0 + resolution: "ts-dedent@npm:2.2.0" + checksum: 93ed8f7878b6d5ed3c08d99b740010eede6bccfe64bce61c5a4da06a2c17d6ddbb80a8c49c2d15251de7594a4f93ffa21dd10e7be75ef66a4dc9951b4a94e2af + languageName: node + linkType: hard + "ts-essentials@npm:^7.0.3": version: 7.0.3 resolution: "ts-essentials@npm:7.0.3"