diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index dc37a8ed124..e0728e65b5d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,11 +2,20 @@ v ✰ Thanks for creating a PR! ✰ ☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > --> - + closes: #XXXX refs: #XXXX + + ## Description diff --git a/.github/actions/restore-node/action.yml b/.github/actions/restore-node/action.yml index 5797145945d..61ab970341a 100644 --- a/.github/actions/restore-node/action.yml +++ b/.github/actions/restore-node/action.yml @@ -41,10 +41,11 @@ runs: persist-credentials: false path: ${{ inputs.path }} - # Select a branch on Endo to test against by adding text to the body of the - # pull request. For example: #endo-branch: some-pr-branch - # The default is 'NOPE' to indicate not to check out Endo, just use - # the published NPM packages. + # Select an Endo target against which to test, defaulting to 'NOPE' for use + # of internally-referenced NPM packages but allowing overrides in the pull + # request description for referencing a branch of the + # [endo repository](https://github.com/endojs/endo) using lines like + # `#endo-branch: rank-strings-by-codepoint` - name: Get the appropriate Endo branch id: endo-branch uses: actions/github-script@v7 @@ -53,8 +54,8 @@ runs: script: |- let branch = 'NOPE'; if (${{ inputs.ignore-endo-branch }}) { - // Skip endo branch - } else if (context.eventName === 'schedule') { + // Skip any override directive. + } else if (context.eventName === 'schedule') { branch = 'master'; } else if (context.payload.pull_request) { const { body } = context.payload.pull_request; @@ -85,7 +86,7 @@ runs: if: steps.endo-branch.outputs.result != 'NOPE' uses: actions/checkout@v4 with: - repository: agoric/endo + repository: endojs/endo path: ./replacement-endo ref: ${{ steps.endo-branch.outputs.result }} clean: 'false' diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index a01d25ebad1..4ae7458e4d3 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -35,8 +35,10 @@ jobs: pre_check: uses: ./.github/workflows/pre-check-integration.yml - # This job is meant to emulate what developers working with the Agoric platform will experience - # It should be kept in sync with https://agoric.com/documentation/getting-started/ + # This job is meant to emulate what developers working with the Agoric + # platform will experience. + # It should be kept in sync with the "getting started" workflow at + # https://docs.agoric.com/guides/getting-started/ getting-started: needs: pre_check if: needs.pre_check.outputs.should_run == 'true' @@ -60,9 +62,11 @@ jobs: node-version: 18.18 keep-endo: 'true' - # Select a branch on dapp to test against by adding text to the body of the - # pull request. For example: #getting-started-branch: zoe-release-0.7.0 - # The default is 'main' + # Select a branch of the + # [default dapp repository](https://github.com/Agoric/dapp-offer-up) (cf. + # packages/agoric-cli/src/main.js) against which to test, defaulting to + # 'main' but allowing overrides in the pull request description using + # lines like `#getting-started-branch: zoe-release-0.7.0` - name: Get the appropriate dapp branch id: get-branch uses: actions/github-script@v7 @@ -138,9 +142,10 @@ jobs: # the chances the content of snapshots may deviate between validators xsnap-random-init: '1' - # Select a branch on loadgen to test against by adding text to the body of the - # pull request. For example: #loadgen-branch: user-123-update-foo - # The default is 'main' + # Select a branch of the + # [load generator dapp repository](https://github.com/Agoric/testnet-load-generator) + # to use, defaulting to 'main' but allowing overrides in the pull request + # description using lines like `#loadgen-branch: ceelab` - name: Get the appropriate loadgen branch id: get-loadgen-branch uses: actions/github-script@v7 diff --git a/.github/workflows/test-documentation.yml b/.github/workflows/test-documentation.yml index bade8a4cd19..596bb60a075 100644 --- a/.github/workflows/test-documentation.yml +++ b/.github/workflows/test-documentation.yml @@ -26,9 +26,11 @@ jobs: node-version: ${{ matrix.node-version }} path: ./agoric-sdk - # Select a branch on dapp to test against by adding text to the body of the - # pull request. For example: #dapp-encouragement-branch: zoe-release-0.7.0 - # The default is 'main' + # Select a branch of the + # [documentation repository](https://github.com/Agoric/documentation) + # against which to test, defaulting to 'main' but allowing overrides in + # the pull request description using lines like + # `#documentation-branch: node-22` - name: Get the appropriate dapp branch id: get-branch uses: actions/github-script@v7 @@ -44,7 +46,7 @@ jobs: branch = result[1]; } } - console.log(branch); + console.log('documentation branch: ' + branch); return branch; - name: Check out dapp diff --git a/a3p-integration/package.json b/a3p-integration/package.json index a3f253cbf7c..ee9bb0a570a 100644 --- a/a3p-integration/package.json +++ b/a3p-integration/package.json @@ -1,7 +1,7 @@ { "private": true, "agoricSyntheticChain": { - "fromTag": "use-vaults-auctions" + "fromTag": "use-upgrade-17" }, "scripts": { "build": "yarn run build:sdk && yarn run build:submissions && yarn run build:synthetic-chain", diff --git a/a3p-integration/proposals/f:replace-price-feeds/.yarnrc.yml b/a3p-integration/proposals/f:replace-price-feeds/.yarnrc.yml deleted file mode 100644 index 3186f3f0795..00000000000 --- a/a3p-integration/proposals/f:replace-price-feeds/.yarnrc.yml +++ /dev/null @@ -1 +0,0 @@ -nodeLinker: node-modules diff --git a/a3p-integration/proposals/f:replace-price-feeds/README.md b/a3p-integration/proposals/f:replace-price-feeds/README.md deleted file mode 100644 index 414bb07fe81..00000000000 --- a/a3p-integration/proposals/f:replace-price-feeds/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# CoreEvalProposal to replace existing price_feed and scaledPriceAuthority vats -# with new contracts. Auctions will need to be replaced, and Vaults will need to -# get at least a null upgrade in order to make use of the new prices. Oracle -# operators will need to accept new invitations, and sync to the roundId (0) of -# the new contracts in order to feed the new pipelines. - -The `submission` for this proposal is automatically generated during `yarn build` -in [a3p-integration](../..) using the code in agoric-sdk through -[build-all-submissions.sh](../../scripts/build-all-submissions.sh) and -[build-submission.sh](../../scripts/build-submission.sh). diff --git a/a3p-integration/proposals/f:replace-price-feeds/agd-tools.js b/a3p-integration/proposals/f:replace-price-feeds/agd-tools.js deleted file mode 100644 index c94718bc1ba..00000000000 --- a/a3p-integration/proposals/f:replace-price-feeds/agd-tools.js +++ /dev/null @@ -1,23 +0,0 @@ -import { agd } from '@agoric/synthetic-chain'; - -export const BID_OFFER_ID = 'bid-vaultUpgrade-test3'; - -/** @param {string} path */ -export const queryVstorage = path => - agd.query('vstorage', 'data', '--output', 'json', path); - -export const getOracleInstance = async price => { - const instanceRec = await queryVstorage(`published.agoricNames.instance`); - - const value = JSON.parse(instanceRec.value); - const body = JSON.parse(value.values.at(-1)); - - const feeds = JSON.parse(body.body.substring(1)); - const feedName = `${price}-USD price feed`; - - const key = Object.keys(feeds).find(k => feeds[k][0] === feedName); - if (key) { - return body.slots[key]; - } - return null; -}; diff --git a/a3p-integration/proposals/f:replace-price-feeds/agoric-tools.js b/a3p-integration/proposals/f:replace-price-feeds/agoric-tools.js deleted file mode 100644 index 1c6e10ac8f6..00000000000 --- a/a3p-integration/proposals/f:replace-price-feeds/agoric-tools.js +++ /dev/null @@ -1,96 +0,0 @@ -import assert from 'node:assert'; -import { agops, agoric, executeOffer } from '@agoric/synthetic-chain'; - -export const generateVaultDirectorParamChange = async ( - previousOfferId, - voteDur, - params, - paramsPath, -) => { - const voteDurSec = BigInt(voteDur); - const toSec = ms => BigInt(Math.round(ms / 1000)); - - const id = `propose-${Date.now()}`; - const deadline = toSec(Date.now()) + voteDurSec; - - const zip = (xs, ys) => xs.map((x, i) => [x, ys[i]]); - // KLUDGE: partial deconstruction of smallCaps values - const fromSmallCapsEntries = txt => { - const { body, slots } = JSON.parse(txt); - const theEntries = zip(JSON.parse(body.slice(1)), slots).map( - ([[name, ref], boardID]) => { - const iface = ref.replace(/^\$\d+\./, ''); - return [name, { iface, boardID }]; - }, - ); - return Object.fromEntries(theEntries); - }; - - const slots = []; // XXX global mutable state - const smallCaps = { - Nat: n => `+${n}`, - // XXX mutates obj - ref: obj => { - if (obj.ix) return obj.ix; - const ix = slots.length; - slots.push(obj.boardID); - obj.ix = `$${ix}.Alleged: ${obj.iface}`; - return obj.ix; - }, - }; - - await null; - const instance = fromSmallCapsEntries( - await agoric.follow('-lF', ':published.agoricNames.instance', '-o', 'text'), - ); - assert(instance.VaultFactory); - - const body = { - method: 'executeOffer', - offer: { - id, - invitationSpec: { - invitationMakerName: 'VoteOnParamChange', - previousOffer: previousOfferId, - source: 'continuing', - }, - offerArgs: { - deadline: smallCaps.Nat(deadline), - instance: smallCaps.ref(instance.VaultFactory), - params, - path: paramsPath, - }, - proposal: {}, - }, - }; - - const capData = { body: `#${JSON.stringify(body)}`, slots }; - return JSON.stringify(capData); -}; - -export const proposeVaultDirectorParamChange = async ( - address, - params, - path, -) => { - const charterAcceptOfferId = await agops.ec( - 'find-continuing-id', - '--for', - `${'charter\\ member\\ invitation'}`, - '--from', - address, - ); - - return executeOffer( - address, - generateVaultDirectorParamChange(charterAcceptOfferId, 30, params, path), - ); -}; - -export const voteForNewParams = (accounts, position) => { - return Promise.all( - accounts.map(account => - agops.ec('vote', '--forPosition', position, '--send-from', account), - ), - ); -}; diff --git a/a3p-integration/proposals/f:replace-price-feeds/package.json b/a3p-integration/proposals/f:replace-price-feeds/package.json deleted file mode 100644 index ca4637e9cdb..00000000000 --- a/a3p-integration/proposals/f:replace-price-feeds/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "agoricProposal": { - "source": "subdir", - "sdk-generate": [ - "inter-protocol/updatePriceFeeds.js submission A3P_INTEGRATION", - "vats/add-auction.js submission", - "vats/upgradeVaults.js submission", - "inter-protocol/updatePriceFeeds.js submission/main main", - "vats/add-auction.js submission/main", - "vats/upgradeVaults.js submission/main", - "inter-protocol/updatePriceFeeds.js submission/devnet devnet", - "vats/add-auction.js submission/devnet", - "vats/upgradeVaults.js submission/devnet" - ], - "type": "/agoric.swingset.CoreEvalProposal" - }, - "type": "module", - "license": "Apache-2.0", - "dependencies": { - "@agoric/synthetic-chain": "^0.3.0", - "ava": "^5.3.1" - }, - "ava": { - "concurrency": 1, - "timeout": "2m", - "files": [ - "!submission" - ] - }, - "scripts": { - "agops": "yarn --cwd /usr/src/agoric-sdk/ --silent agops" - }, - "packageManager": "yarn@4.2.2" -} diff --git a/a3p-integration/proposals/f:replace-price-feeds/test.sh b/a3p-integration/proposals/f:replace-price-feeds/test.sh deleted file mode 100755 index 23a194f7f79..00000000000 --- a/a3p-integration/proposals/f:replace-price-feeds/test.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -# Place here any test that should be executed using the proposal. -# The effects of this step are not persisted in further layers. - -yarn ava ./*.test.js diff --git a/a3p-integration/proposals/f:replace-price-feeds/yarn.lock b/a3p-integration/proposals/f:replace-price-feeds/yarn.lock deleted file mode 100644 index ee7a03e8e81..00000000000 --- a/a3p-integration/proposals/f:replace-price-feeds/yarn.lock +++ /dev/null @@ -1,2345 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@agoric/synthetic-chain@npm:^0.3.0": - version: 0.3.0 - resolution: "@agoric/synthetic-chain@npm:0.3.0" - dependencies: - "@endo/zip": "npm:^1.0.7" - better-sqlite3: "npm:^9.6.0" - chalk: "npm:^5.3.0" - cosmjs-types: "npm:^0.9.0" - execa: "npm:^9.3.1" - bin: - synthetic-chain: dist/cli/cli.js - checksum: 10c0/17c6241bdc48b8a2a7608c9d4d7c0a0c76fb10d4ee44a31a1150104a792bcd1133f4b1a7e8ab26673a07450b3ceabccd9911999117568221b49221b6ee4306a1 - languageName: node - linkType: hard - -"@endo/zip@npm:^1.0.7": - version: 1.0.7 - resolution: "@endo/zip@npm:1.0.7" - checksum: 10c0/a1c0d155448ce877012b34c8fe8cd3a58de9eb807514c81cddeebb802ee8e552b27d8a9a40fab3f3e4c49e0cb7fea6902fa1dd12a23ff6f30b56161fc3edc1f8 - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@nodelib/fs.scandir@npm:2.1.5": - version: 2.1.5 - resolution: "@nodelib/fs.scandir@npm:2.1.5" - dependencies: - "@nodelib/fs.stat": "npm:2.0.5" - run-parallel: "npm:^1.1.9" - checksum: 10c0/732c3b6d1b1e967440e65f284bd06e5821fedf10a1bea9ed2bb75956ea1f30e08c44d3def9d6a230666574edbaf136f8cfd319c14fd1f87c66e6a44449afb2eb - languageName: node - linkType: hard - -"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": - version: 2.0.5 - resolution: "@nodelib/fs.stat@npm:2.0.5" - checksum: 10c0/88dafe5e3e29a388b07264680dc996c17f4bda48d163a9d4f5c1112979f0ce8ec72aa7116122c350b4e7976bc5566dc3ddb579be1ceaacc727872eb4ed93926d - languageName: node - linkType: hard - -"@nodelib/fs.walk@npm:^1.2.3": - version: 1.2.8 - resolution: "@nodelib/fs.walk@npm:1.2.8" - dependencies: - "@nodelib/fs.scandir": "npm:2.1.5" - fastq: "npm:^1.6.0" - checksum: 10c0/db9de047c3bb9b51f9335a7bb46f4fcfb6829fb628318c12115fbaf7d369bfce71c15b103d1fc3b464812d936220ee9bc1c8f762d032c9f6be9acc99249095b1 - languageName: node - linkType: hard - -"@npmcli/agent@npm:^2.0.0": - version: 2.2.2 - resolution: "@npmcli/agent@npm:2.2.2" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae - languageName: node - linkType: hard - -"@npmcli/fs@npm:^3.1.0": - version: 3.1.1 - resolution: "@npmcli/fs@npm:3.1.1" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@sec-ant/readable-stream@npm:^0.4.1": - version: 0.4.1 - resolution: "@sec-ant/readable-stream@npm:0.4.1" - checksum: 10c0/64e9e9cf161e848067a5bf60cdc04d18495dc28bb63a8d9f8993e4dd99b91ad34e4b563c85de17d91ffb177ec17a0664991d2e115f6543e73236a906068987af - languageName: node - linkType: hard - -"@sindresorhus/merge-streams@npm:^4.0.0": - version: 4.0.0 - resolution: "@sindresorhus/merge-streams@npm:4.0.0" - checksum: 10c0/482ee543629aa1933b332f811a1ae805a213681ecdd98c042b1c1b89387df63e7812248bb4df3910b02b3cc5589d3d73e4393f30e197c9dde18046ccd471fc6b - languageName: node - linkType: hard - -"abbrev@npm:^2.0.0": - version: 2.0.0 - resolution: "abbrev@npm:2.0.0" - checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 - languageName: node - linkType: hard - -"acorn-walk@npm:^8.2.0": - version: 8.3.4 - resolution: "acorn-walk@npm:8.3.4" - dependencies: - acorn: "npm:^8.11.0" - checksum: 10c0/76537ac5fb2c37a64560feaf3342023dadc086c46da57da363e64c6148dc21b57d49ace26f949e225063acb6fb441eabffd89f7a3066de5ad37ab3e328927c62 - languageName: node - linkType: hard - -"acorn@npm:^8.11.0, acorn@npm:^8.8.2": - version: 8.12.1 - resolution: "acorn@npm:8.12.1" - bin: - acorn: bin/acorn - checksum: 10c0/51fb26cd678f914e13287e886da2d7021f8c2bc0ccc95e03d3e0447ee278dd3b40b9c57dc222acd5881adcf26f3edc40901a4953403232129e3876793cd17386 - languageName: node - linkType: hard - -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": - version: 7.1.1 - resolution: "agent-base@npm:7.1.1" - dependencies: - debug: "npm:^4.3.4" - checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: "npm:^2.0.0" - indent-string: "npm:^4.0.0" - checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 - languageName: node - linkType: hard - -"aggregate-error@npm:^4.0.0": - version: 4.0.1 - resolution: "aggregate-error@npm:4.0.1" - dependencies: - clean-stack: "npm:^4.0.0" - indent-string: "npm:^5.0.0" - checksum: 10c0/75fd739f5c4c60a667cce35ccaf0edf135e147ef0be9a029cab75de14ac9421779b15339d562e58d25b233ea0ef2bbd4c916f149fdbcb73c2b9a62209e611343 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c - languageName: node - linkType: hard - -"anymatch@npm:~3.1.2": - version: 3.1.3 - resolution: "anymatch@npm:3.1.3" - dependencies: - normalize-path: "npm:^3.0.0" - picomatch: "npm:^2.0.4" - checksum: 10c0/57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac - languageName: node - linkType: hard - -"argparse@npm:^1.0.7": - version: 1.0.10 - resolution: "argparse@npm:1.0.10" - dependencies: - sprintf-js: "npm:~1.0.2" - checksum: 10c0/b2972c5c23c63df66bca144dbc65d180efa74f25f8fd9b7d9a0a6c88ae839db32df3d54770dcb6460cf840d232b60695d1a6b1053f599d84e73f7437087712de - languageName: node - linkType: hard - -"array-find-index@npm:^1.0.1": - version: 1.0.2 - resolution: "array-find-index@npm:1.0.2" - checksum: 10c0/86b9485c74ddd324feab807e10a6de3f9c1683856267236fac4bb4d4667ada6463e106db3f6c540ae6b720e0442b590ec701d13676df4c6af30ebf4da09b4f57 - languageName: node - linkType: hard - -"arrgv@npm:^1.0.2": - version: 1.0.2 - resolution: "arrgv@npm:1.0.2" - checksum: 10c0/7e6e782e6b749923ac7cbc4048ef6fe0844c4a59bfc8932fcd4c44566ba25eed46501f94dd7cf3c7297da88f3f599ca056bfb77d0c2484aebc92f04239f69124 - languageName: node - linkType: hard - -"arrify@npm:^3.0.0": - version: 3.0.0 - resolution: "arrify@npm:3.0.0" - checksum: 10c0/2e26601b8486f29780f1f70f7ac05a226755814c2a3ab42e196748f650af1dc310cd575a11dd4b9841c70fd7460b2dd2b8fe6fb7a3375878e2660706efafa58e - languageName: node - linkType: hard - -"ava@npm:^5.3.1": - version: 5.3.1 - resolution: "ava@npm:5.3.1" - dependencies: - acorn: "npm:^8.8.2" - acorn-walk: "npm:^8.2.0" - ansi-styles: "npm:^6.2.1" - arrgv: "npm:^1.0.2" - arrify: "npm:^3.0.0" - callsites: "npm:^4.0.0" - cbor: "npm:^8.1.0" - chalk: "npm:^5.2.0" - chokidar: "npm:^3.5.3" - chunkd: "npm:^2.0.1" - ci-info: "npm:^3.8.0" - ci-parallel-vars: "npm:^1.0.1" - clean-yaml-object: "npm:^0.1.0" - cli-truncate: "npm:^3.1.0" - code-excerpt: "npm:^4.0.0" - common-path-prefix: "npm:^3.0.0" - concordance: "npm:^5.0.4" - currently-unhandled: "npm:^0.4.1" - debug: "npm:^4.3.4" - emittery: "npm:^1.0.1" - figures: "npm:^5.0.0" - globby: "npm:^13.1.4" - ignore-by-default: "npm:^2.1.0" - indent-string: "npm:^5.0.0" - is-error: "npm:^2.2.2" - is-plain-object: "npm:^5.0.0" - is-promise: "npm:^4.0.0" - matcher: "npm:^5.0.0" - mem: "npm:^9.0.2" - ms: "npm:^2.1.3" - p-event: "npm:^5.0.1" - p-map: "npm:^5.5.0" - picomatch: "npm:^2.3.1" - pkg-conf: "npm:^4.0.0" - plur: "npm:^5.1.0" - pretty-ms: "npm:^8.0.0" - resolve-cwd: "npm:^3.0.0" - stack-utils: "npm:^2.0.6" - strip-ansi: "npm:^7.0.1" - supertap: "npm:^3.0.1" - temp-dir: "npm:^3.0.0" - write-file-atomic: "npm:^5.0.1" - yargs: "npm:^17.7.2" - peerDependencies: - "@ava/typescript": "*" - peerDependenciesMeta: - "@ava/typescript": - optional: true - bin: - ava: entrypoints/cli.mjs - checksum: 10c0/262cbdb9e8c3ce7177be91b92ba521e9d5aef577dcc8095cc591f86baaa291b91c88925928f5d26832c4d1b381a6ae99f2e8804077c592d0d32322c1212605cc - languageName: node - linkType: hard - -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - -"base64-js@npm:^1.3.1": - version: 1.5.1 - resolution: "base64-js@npm:1.5.1" - checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf - languageName: node - linkType: hard - -"better-sqlite3@npm:^9.6.0": - version: 9.6.0 - resolution: "better-sqlite3@npm:9.6.0" - dependencies: - bindings: "npm:^1.5.0" - node-gyp: "npm:latest" - prebuild-install: "npm:^7.1.1" - checksum: 10c0/8db9b38f414e26a56d4c40fc16e94a253118491dae0e2c054338a9e470f1a883c7eb4cb330f2f5737db30f704d4f2e697c59071ca04e03364ee9fe04375aa9c8 - languageName: node - linkType: hard - -"binary-extensions@npm:^2.0.0": - version: 2.3.0 - resolution: "binary-extensions@npm:2.3.0" - checksum: 10c0/75a59cafc10fb12a11d510e77110c6c7ae3f4ca22463d52487709ca7f18f69d886aa387557cc9864fbdb10153d0bdb4caacabf11541f55e89ed6e18d12ece2b5 - languageName: node - linkType: hard - -"bindings@npm:^1.5.0": - version: 1.5.0 - resolution: "bindings@npm:1.5.0" - dependencies: - file-uri-to-path: "npm:1.0.0" - checksum: 10c0/3dab2491b4bb24124252a91e656803eac24292473e56554e35bbfe3cc1875332cfa77600c3bac7564049dc95075bf6fcc63a4609920ff2d64d0fe405fcf0d4ba - languageName: node - linkType: hard - -"bl@npm:^4.0.3": - version: 4.1.0 - resolution: "bl@npm:4.1.0" - dependencies: - buffer: "npm:^5.5.0" - inherits: "npm:^2.0.4" - readable-stream: "npm:^3.4.0" - checksum: 10c0/02847e1d2cb089c9dc6958add42e3cdeaf07d13f575973963335ac0fdece563a50ac770ac4c8fa06492d2dd276f6cc3b7f08c7cd9c7a7ad0f8d388b2a28def5f - languageName: node - linkType: hard - -"blueimp-md5@npm:^2.10.0": - version: 2.19.0 - resolution: "blueimp-md5@npm:2.19.0" - checksum: 10c0/85d04343537dd99a288c62450341dcce7380d3454c81f8e5a971ddd80307d6f9ef51b5b92ad7d48aaaa92fd6d3a1f6b2f4fada068faae646887f7bfabc17a346 - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - -"braces@npm:^3.0.3, braces@npm:~3.0.2": - version: 3.0.3 - resolution: "braces@npm:3.0.3" - dependencies: - fill-range: "npm:^7.1.1" - checksum: 10c0/7c6dfd30c338d2997ba77500539227b9d1f85e388a5f43220865201e407e076783d0881f2d297b9f80951b4c957fcf0b51c1d2d24227631643c3f7c284b0aa04 - languageName: node - linkType: hard - -"buffer@npm:^5.5.0": - version: 5.7.1 - resolution: "buffer@npm:5.7.1" - dependencies: - base64-js: "npm:^1.3.1" - ieee754: "npm:^1.1.13" - checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e - languageName: node - linkType: hard - -"cacache@npm:^18.0.0": - version: 18.0.4 - resolution: "cacache@npm:18.0.4" - dependencies: - "@npmcli/fs": "npm:^3.1.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^4.0.0" - ssri: "npm:^10.0.0" - tar: "npm:^6.1.11" - unique-filename: "npm:^3.0.0" - checksum: 10c0/6c055bafed9de4f3dcc64ac3dc7dd24e863210902b7c470eb9ce55a806309b3efff78033e3d8b4f7dcc5d467f2db43c6a2857aaaf26f0094b8a351d44c42179f - languageName: node - linkType: hard - -"callsites@npm:^4.0.0": - version: 4.2.0 - resolution: "callsites@npm:4.2.0" - checksum: 10c0/8f7e269ec09fc0946bb22d838a8bc7932e1909ab4a833b964749f4d0e8bdeaa1f253287c4f911f61781f09620b6925ccd19a5ea4897489c4e59442c660c312a3 - languageName: node - linkType: hard - -"cbor@npm:^8.1.0": - version: 8.1.0 - resolution: "cbor@npm:8.1.0" - dependencies: - nofilter: "npm:^3.1.0" - checksum: 10c0/a836e2e7ea0efb1b9c4e5a4be906c57113d730cc42293a34072e0164ed110bb8ac035dc7dca2e3ebb641bd4b37e00fdbbf09c951aa864b3d4888a6ed8c6243f7 - languageName: node - linkType: hard - -"chalk@npm:^5.2.0, chalk@npm:^5.3.0": - version: 5.3.0 - resolution: "chalk@npm:5.3.0" - checksum: 10c0/8297d436b2c0f95801103ff2ef67268d362021b8210daf8ddbe349695333eb3610a71122172ff3b0272f1ef2cf7cc2c41fdaa4715f52e49ffe04c56340feed09 - languageName: node - linkType: hard - -"chokidar@npm:^3.5.3": - version: 3.6.0 - resolution: "chokidar@npm:3.6.0" - dependencies: - anymatch: "npm:~3.1.2" - braces: "npm:~3.0.2" - fsevents: "npm:~2.3.2" - glob-parent: "npm:~5.1.2" - is-binary-path: "npm:~2.1.0" - is-glob: "npm:~4.0.1" - normalize-path: "npm:~3.0.0" - readdirp: "npm:~3.6.0" - dependenciesMeta: - fsevents: - optional: true - checksum: 10c0/8361dcd013f2ddbe260eacb1f3cb2f2c6f2b0ad118708a343a5ed8158941a39cb8fb1d272e0f389712e74ee90ce8ba864eece9e0e62b9705cb468a2f6d917462 - languageName: node - linkType: hard - -"chownr@npm:^1.1.1": - version: 1.1.4 - resolution: "chownr@npm:1.1.4" - checksum: 10c0/ed57952a84cc0c802af900cf7136de643d3aba2eecb59d29344bc2f3f9bf703a301b9d84cdc71f82c3ffc9ccde831b0d92f5b45f91727d6c9da62f23aef9d9db - languageName: node - linkType: hard - -"chownr@npm:^2.0.0": - version: 2.0.0 - resolution: "chownr@npm:2.0.0" - checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 - languageName: node - linkType: hard - -"chunkd@npm:^2.0.1": - version: 2.0.1 - resolution: "chunkd@npm:2.0.1" - checksum: 10c0/4e0c5aac6048ecedfa4cd0a5f6c4f010c70a7b7645aeca7bfeb47cb0733c3463054f0ced3f2667b2e0e67edd75d68a8e05481b01115ba3f8a952a93026254504 - languageName: node - linkType: hard - -"ci-info@npm:^3.8.0": - version: 3.9.0 - resolution: "ci-info@npm:3.9.0" - checksum: 10c0/6f0109e36e111684291d46123d491bc4e7b7a1934c3a20dea28cba89f1d4a03acd892f5f6a81ed3855c38647e285a150e3c9ba062e38943bef57fee6c1554c3a - languageName: node - linkType: hard - -"ci-parallel-vars@npm:^1.0.1": - version: 1.0.1 - resolution: "ci-parallel-vars@npm:1.0.1" - checksum: 10c0/80952f699cbbc146092b077b4f3e28d085620eb4e6be37f069b4dbb3db0ee70e8eec3beef4ebe70ff60631e9fc743b9d0869678489f167442cac08b260e5ac08 - languageName: node - linkType: hard - -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 - languageName: node - linkType: hard - -"clean-stack@npm:^4.0.0": - version: 4.2.0 - resolution: "clean-stack@npm:4.2.0" - dependencies: - escape-string-regexp: "npm:5.0.0" - checksum: 10c0/2bdf981a0fef0a23c14255df693b30eb9ae27eedf212470d8c400a0c0b6fb82fbf1ff8c5216ccd5721e3670b700389c886b1dce5070776dc9fbcc040957758c0 - languageName: node - linkType: hard - -"clean-yaml-object@npm:^0.1.0": - version: 0.1.0 - resolution: "clean-yaml-object@npm:0.1.0" - checksum: 10c0/a6505310590038afb9f0adc7f17a4c66787719c94d23f8491267ea4d9c405cdd378bd576ae1926169b6d997d4c59a8b86516bf4d16ba228280cf615598c58e05 - languageName: node - linkType: hard - -"cli-truncate@npm:^3.1.0": - version: 3.1.0 - resolution: "cli-truncate@npm:3.1.0" - dependencies: - slice-ansi: "npm:^5.0.0" - string-width: "npm:^5.0.0" - checksum: 10c0/a19088878409ec0e5dc2659a5166929629d93cfba6d68afc9cde2282fd4c751af5b555bf197047e31c87c574396348d011b7aa806fec29c4139ea4f7f00b324c - languageName: node - linkType: hard - -"cliui@npm:^8.0.1": - version: 8.0.1 - resolution: "cliui@npm:8.0.1" - dependencies: - string-width: "npm:^4.2.0" - strip-ansi: "npm:^6.0.1" - wrap-ansi: "npm:^7.0.0" - checksum: 10c0/4bda0f09c340cbb6dfdc1ed508b3ca080f12992c18d68c6be4d9cf51756033d5266e61ec57529e610dacbf4da1c634423b0c1b11037709cc6b09045cbd815df5 - languageName: node - linkType: hard - -"code-excerpt@npm:^4.0.0": - version: 4.0.0 - resolution: "code-excerpt@npm:4.0.0" - dependencies: - convert-to-spaces: "npm:^2.0.1" - checksum: 10c0/b6c5a06e039cecd2ab6a0e10ee0831de8362107d1f298ca3558b5f9004cb8e0260b02dd6c07f57b9a0e346c76864d2873311ee1989809fdeb05bd5fbbadde773 - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"common-path-prefix@npm:^3.0.0": - version: 3.0.0 - resolution: "common-path-prefix@npm:3.0.0" - checksum: 10c0/c4a74294e1b1570f4a8ab435285d185a03976c323caa16359053e749db4fde44e3e6586c29cd051100335e11895767cbbd27ea389108e327d62f38daf4548fdb - languageName: node - linkType: hard - -"concordance@npm:^5.0.4": - version: 5.0.4 - resolution: "concordance@npm:5.0.4" - dependencies: - date-time: "npm:^3.1.0" - esutils: "npm:^2.0.3" - fast-diff: "npm:^1.2.0" - js-string-escape: "npm:^1.0.1" - lodash: "npm:^4.17.15" - md5-hex: "npm:^3.0.1" - semver: "npm:^7.3.2" - well-known-symbols: "npm:^2.0.0" - checksum: 10c0/59b440f330df3a7c9aa148ba588b3e99aed86acab225b4f01ffcea34ace4cf11f817e31153254e8f38ed48508998dad40b9106951a743c334d751f7ab21afb8a - languageName: node - linkType: hard - -"convert-to-spaces@npm:^2.0.1": - version: 2.0.1 - resolution: "convert-to-spaces@npm:2.0.1" - checksum: 10c0/d90aa0e3b6a27f9d5265a8d32def3c5c855b3e823a9db1f26d772f8146d6b91020a2fdfd905ce8048a73fad3aaf836fef8188c67602c374405e2ae8396c4ac46 - languageName: node - linkType: hard - -"cosmjs-types@npm:^0.9.0": - version: 0.9.0 - resolution: "cosmjs-types@npm:0.9.0" - checksum: 10c0/bc20f4293fb34629d7c5f96bafe533987f753df957ff68eb078d0128ae5a418320cb945024441769a07bb9bc5dde9d22b972fd40d485933e5706ea191c43727b - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.3": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 - languageName: node - linkType: hard - -"currently-unhandled@npm:^0.4.1": - version: 0.4.1 - resolution: "currently-unhandled@npm:0.4.1" - dependencies: - array-find-index: "npm:^1.0.1" - checksum: 10c0/32d197689ec32f035910202c1abb0dc6424dce01d7b51779c685119b380d98535c110ffff67a262fc7e367612a7dfd30d3d3055f9a6634b5a9dd1302de7ef11c - languageName: node - linkType: hard - -"date-time@npm:^3.1.0": - version: 3.1.0 - resolution: "date-time@npm:3.1.0" - dependencies: - time-zone: "npm:^1.0.0" - checksum: 10c0/aa3e2e930d74b0b9e90f69de7a16d3376e30f21f1f4ce9a2311d8fec32d760e776efea752dafad0ce188187265235229013036202be053fc2d7979813bfb6ded - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:^4.3.4": - version: 4.3.7 - resolution: "debug@npm:4.3.7" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/1471db19c3b06d485a622d62f65947a19a23fbd0dd73f7fd3eafb697eec5360cde447fb075919987899b1a2096e85d35d4eb5a4de09a57600ac9cf7e6c8e768b - languageName: node - linkType: hard - -"decompress-response@npm:^6.0.0": - version: 6.0.0 - resolution: "decompress-response@npm:6.0.0" - dependencies: - mimic-response: "npm:^3.1.0" - checksum: 10c0/bd89d23141b96d80577e70c54fb226b2f40e74a6817652b80a116d7befb8758261ad073a8895648a29cc0a5947021ab66705cb542fa9c143c82022b27c5b175e - languageName: node - linkType: hard - -"deep-extend@npm:^0.6.0": - version: 0.6.0 - resolution: "deep-extend@npm:0.6.0" - checksum: 10c0/1c6b0abcdb901e13a44c7d699116d3d4279fdb261983122a3783e7273844d5f2537dc2e1c454a23fcf645917f93fbf8d07101c1d03c015a87faa662755212566 - languageName: node - linkType: hard - -"detect-libc@npm:^2.0.0": - version: 2.0.3 - resolution: "detect-libc@npm:2.0.3" - checksum: 10c0/88095bda8f90220c95f162bf92cad70bd0e424913e655c20578600e35b91edc261af27531cf160a331e185c0ced93944bc7e09939143225f56312d7fd800fdb7 - languageName: node - linkType: hard - -"dir-glob@npm:^3.0.1": - version: 3.0.1 - resolution: "dir-glob@npm:3.0.1" - dependencies: - path-type: "npm:^4.0.0" - checksum: 10c0/dcac00920a4d503e38bb64001acb19df4efc14536ada475725e12f52c16777afdee4db827f55f13a908ee7efc0cb282e2e3dbaeeb98c0993dd93d1802d3bf00c - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"emittery@npm:^1.0.1": - version: 1.0.3 - resolution: "emittery@npm:1.0.3" - checksum: 10c0/91605d044f3891dd1f8ab731aeb94b520488b21e707f7064dcbcf5303bac3b4e7133dfa23c343ede1fc970340bd78a9b1aed522b805bc15104606bba630dd71e - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": - version: 1.4.4 - resolution: "end-of-stream@npm:1.4.4" - dependencies: - once: "npm:^1.4.0" - checksum: 10c0/870b423afb2d54bb8d243c63e07c170409d41e20b47eeef0727547aea5740bd6717aca45597a9f2745525667a6b804c1e7bede41f856818faee5806dd9ff3975 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"escalade@npm:^3.1.1": - version: 3.2.0 - resolution: "escalade@npm:3.2.0" - checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 - languageName: node - linkType: hard - -"escape-string-regexp@npm:5.0.0, escape-string-regexp@npm:^5.0.0": - version: 5.0.0 - resolution: "escape-string-regexp@npm:5.0.0" - checksum: 10c0/6366f474c6f37a802800a435232395e04e9885919873e382b157ab7e8f0feb8fed71497f84a6f6a81a49aab41815522f5839112bd38026d203aea0c91622df95 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^2.0.0": - version: 2.0.0 - resolution: "escape-string-regexp@npm:2.0.0" - checksum: 10c0/2530479fe8db57eace5e8646c9c2a9c80fa279614986d16dcc6bcaceb63ae77f05a851ba6c43756d816c61d7f4534baf56e3c705e3e0d884818a46808811c507 - languageName: node - linkType: hard - -"esprima@npm:^4.0.0": - version: 4.0.1 - resolution: "esprima@npm:4.0.1" - bin: - esparse: ./bin/esparse.js - esvalidate: ./bin/esvalidate.js - checksum: 10c0/ad4bab9ead0808cf56501750fd9d3fb276f6b105f987707d059005d57e182d18a7c9ec7f3a01794ebddcca676773e42ca48a32d67a250c9d35e009ca613caba3 - languageName: node - linkType: hard - -"esutils@npm:^2.0.3": - version: 2.0.3 - resolution: "esutils@npm:2.0.3" - checksum: 10c0/9a2fe69a41bfdade834ba7c42de4723c97ec776e40656919c62cbd13607c45e127a003f05f724a1ea55e5029a4cf2de444b13009f2af71271e42d93a637137c7 - languageName: node - linkType: hard - -"execa@npm:^9.3.1": - version: 9.4.0 - resolution: "execa@npm:9.4.0" - dependencies: - "@sindresorhus/merge-streams": "npm:^4.0.0" - cross-spawn: "npm:^7.0.3" - figures: "npm:^6.1.0" - get-stream: "npm:^9.0.0" - human-signals: "npm:^8.0.0" - is-plain-obj: "npm:^4.1.0" - is-stream: "npm:^4.0.1" - npm-run-path: "npm:^6.0.0" - pretty-ms: "npm:^9.0.0" - signal-exit: "npm:^4.1.0" - strip-final-newline: "npm:^4.0.0" - yoctocolors: "npm:^2.0.0" - checksum: 10c0/6ad06c627b5d7bb007bc7b6cc35d7e32b5a3365375ffc8ddbcc12d2423651fa9928ba0c447cc9e60079e505e9b24fbe0a57f80371511d7d20302c04c2d3ce95e - languageName: node - linkType: hard - -"expand-template@npm:^2.0.3": - version: 2.0.3 - resolution: "expand-template@npm:2.0.3" - checksum: 10c0/1c9e7afe9acadf9d373301d27f6a47b34e89b3391b1ef38b7471d381812537ef2457e620ae7f819d2642ce9c43b189b3583813ec395e2938319abe356a9b2f51 - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.1 - resolution: "exponential-backoff@npm:3.1.1" - checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 - languageName: node - linkType: hard - -"fast-diff@npm:^1.2.0": - version: 1.3.0 - resolution: "fast-diff@npm:1.3.0" - checksum: 10c0/5c19af237edb5d5effda008c891a18a585f74bf12953be57923f17a3a4d0979565fc64dbc73b9e20926b9d895f5b690c618cbb969af0cf022e3222471220ad29 - languageName: node - linkType: hard - -"fast-glob@npm:^3.3.0": - version: 3.3.2 - resolution: "fast-glob@npm:3.3.2" - dependencies: - "@nodelib/fs.stat": "npm:^2.0.2" - "@nodelib/fs.walk": "npm:^1.2.3" - glob-parent: "npm:^5.1.2" - merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.4" - checksum: 10c0/42baad7b9cd40b63e42039132bde27ca2cb3a4950d0a0f9abe4639ea1aa9d3e3b40f98b1fe31cbc0cc17b664c9ea7447d911a152fa34ec5b72977b125a6fc845 - languageName: node - linkType: hard - -"fastq@npm:^1.6.0": - version: 1.17.1 - resolution: "fastq@npm:1.17.1" - dependencies: - reusify: "npm:^1.0.4" - checksum: 10c0/1095f16cea45fb3beff558bb3afa74ca7a9250f5a670b65db7ed585f92b4b48381445cd328b3d87323da81e43232b5d5978a8201bde84e0cd514310f1ea6da34 - languageName: node - linkType: hard - -"figures@npm:^5.0.0": - version: 5.0.0 - resolution: "figures@npm:5.0.0" - dependencies: - escape-string-regexp: "npm:^5.0.0" - is-unicode-supported: "npm:^1.2.0" - checksum: 10c0/ce0f17d4ea8b0fc429c5207c343534a2f5284ecfb22aa08607da7dc84ed9e1cf754f5b97760e8dcb98d3c9d1a1e4d3d578fe3b5b99c426f05d0f06c7ba618e16 - languageName: node - linkType: hard - -"figures@npm:^6.1.0": - version: 6.1.0 - resolution: "figures@npm:6.1.0" - dependencies: - is-unicode-supported: "npm:^2.0.0" - checksum: 10c0/9159df4264d62ef447a3931537de92f5012210cf5135c35c010df50a2169377581378149abfe1eb238bd6acbba1c0d547b1f18e0af6eee49e30363cedaffcfe4 - languageName: node - linkType: hard - -"file-uri-to-path@npm:1.0.0": - version: 1.0.0 - resolution: "file-uri-to-path@npm:1.0.0" - checksum: 10c0/3b545e3a341d322d368e880e1c204ef55f1d45cdea65f7efc6c6ce9e0c4d22d802d5629320eb779d006fe59624ac17b0e848d83cc5af7cd101f206cb704f5519 - languageName: node - linkType: hard - -"fill-range@npm:^7.1.1": - version: 7.1.1 - resolution: "fill-range@npm:7.1.1" - dependencies: - to-regex-range: "npm:^5.0.1" - checksum: 10c0/b75b691bbe065472f38824f694c2f7449d7f5004aa950426a2c28f0306c60db9b880c0b0e4ed819997ffb882d1da02cfcfc819bddc94d71627f5269682edf018 - languageName: node - linkType: hard - -"find-up@npm:^6.0.0": - version: 6.3.0 - resolution: "find-up@npm:6.3.0" - dependencies: - locate-path: "npm:^7.1.0" - path-exists: "npm:^5.0.0" - checksum: 10c0/07e0314362d316b2b13f7f11ea4692d5191e718ca3f7264110127520f3347996349bf9e16805abae3e196805814bc66ef4bff2b8904dc4a6476085fc9b0eba07 - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.3.0 - resolution: "foreground-child@npm:3.3.0" - dependencies: - cross-spawn: "npm:^7.0.0" - signal-exit: "npm:^4.0.1" - checksum: 10c0/028f1d41000553fcfa6c4bb5c372963bf3d9bf0b1f25a87d1a6253014343fb69dfb1b42d9625d7cf44c8ba429940f3d0ff718b62105d4d4a4f6ef8ca0a53faa2 - languageName: node - linkType: hard - -"fs-constants@npm:^1.0.0": - version: 1.0.0 - resolution: "fs-constants@npm:1.0.0" - checksum: 10c0/a0cde99085f0872f4d244e83e03a46aa387b74f5a5af750896c6b05e9077fac00e9932fdf5aef84f2f16634cd473c63037d7a512576da7d5c2b9163d1909f3a8 - languageName: node - linkType: hard - -"fs-minipass@npm:^2.0.0": - version: 2.1.0 - resolution: "fs-minipass@npm:2.1.0" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fsevents@npm:~2.3.2": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"get-caller-file@npm:^2.0.5": - version: 2.0.5 - resolution: "get-caller-file@npm:2.0.5" - checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde - languageName: node - linkType: hard - -"get-stream@npm:^9.0.0": - version: 9.0.1 - resolution: "get-stream@npm:9.0.1" - dependencies: - "@sec-ant/readable-stream": "npm:^0.4.1" - is-stream: "npm:^4.0.1" - checksum: 10c0/d70e73857f2eea1826ac570c3a912757dcfbe8a718a033fa0c23e12ac8e7d633195b01710e0559af574cbb5af101009b42df7b6f6b29ceec8dbdf7291931b948 - languageName: node - linkType: hard - -"github-from-package@npm:0.0.0": - version: 0.0.0 - resolution: "github-from-package@npm:0.0.0" - checksum: 10c0/737ee3f52d0a27e26332cde85b533c21fcdc0b09fb716c3f8e522cfaa9c600d4a631dec9fcde179ec9d47cca89017b7848ed4d6ae6b6b78f936c06825b1fcc12 - languageName: node - linkType: hard - -"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": - version: 5.1.2 - resolution: "glob-parent@npm:5.1.2" - dependencies: - is-glob: "npm:^4.0.1" - checksum: 10c0/cab87638e2112bee3f839ef5f6e0765057163d39c66be8ec1602f3823da4692297ad4e972de876ea17c44d652978638d2fd583c6713d0eb6591706825020c9ee - languageName: node - linkType: hard - -"glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.4.5 - resolution: "glob@npm:10.4.5" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"globby@npm:^13.1.4": - version: 13.2.2 - resolution: "globby@npm:13.2.2" - dependencies: - dir-glob: "npm:^3.0.1" - fast-glob: "npm:^3.3.0" - ignore: "npm:^5.2.4" - merge2: "npm:^1.4.1" - slash: "npm:^4.0.0" - checksum: 10c0/a8d7cc7cbe5e1b2d0f81d467bbc5bc2eac35f74eaded3a6c85fc26d7acc8e6de22d396159db8a2fc340b8a342e74cac58de8f4aee74146d3d146921a76062664 - languageName: node - linkType: hard - -"graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1": - version: 7.0.5 - resolution: "https-proxy-agent@npm:7.0.5" - dependencies: - agent-base: "npm:^7.0.2" - debug: "npm:4" - checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c - languageName: node - linkType: hard - -"human-signals@npm:^8.0.0": - version: 8.0.0 - resolution: "human-signals@npm:8.0.0" - checksum: 10c0/e4dac4f7d3eb791ed04129fc6a85bd454a9102d3e3b76c911d0db7057ebd60b2956b435b5b5712aec18960488ede3c21ef7c56e42cdd70760c0d84d3c05cd92e - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"ieee754@npm:^1.1.13": - version: 1.2.1 - resolution: "ieee754@npm:1.2.1" - checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb - languageName: node - linkType: hard - -"ignore-by-default@npm:^2.1.0": - version: 2.1.0 - resolution: "ignore-by-default@npm:2.1.0" - checksum: 10c0/3a6040dac25ed9da39dee73bf1634fdd1e15b0eb7cf52a6bdec81c310565782d8811c104ce40acb3d690d61c5fc38a91c78e6baee830a8a2232424dbc6b66981 - languageName: node - linkType: hard - -"ignore@npm:^5.2.4": - version: 5.3.2 - resolution: "ignore@npm:5.3.2" - checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f - languageName: node - linkType: hard - -"indent-string@npm:^5.0.0": - version: 5.0.0 - resolution: "indent-string@npm:5.0.0" - checksum: 10c0/8ee77b57d92e71745e133f6f444d6fa3ed503ad0e1bcd7e80c8da08b42375c07117128d670589725ed07b1978065803fa86318c309ba45415b7fe13e7f170220 - languageName: node - linkType: hard - -"inherits@npm:^2.0.3, inherits@npm:^2.0.4": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 - languageName: node - linkType: hard - -"ini@npm:~1.3.0": - version: 1.3.8 - resolution: "ini@npm:1.3.8" - checksum: 10c0/ec93838d2328b619532e4f1ff05df7909760b6f66d9c9e2ded11e5c1897d6f2f9980c54dd638f88654b00919ce31e827040631eab0a3969e4d1abefa0719516a - languageName: node - linkType: hard - -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc - languageName: node - linkType: hard - -"irregular-plurals@npm:^3.3.0": - version: 3.5.0 - resolution: "irregular-plurals@npm:3.5.0" - checksum: 10c0/7c033bbe7325e5a6e0a26949cc6863b6ce273403d4cd5b93bd99b33fecb6605b0884097c4259c23ed0c52c2133bf7d1cdcdd7a0630e8c325161fe269b3447918 - languageName: node - linkType: hard - -"is-binary-path@npm:~2.1.0": - version: 2.1.0 - resolution: "is-binary-path@npm:2.1.0" - dependencies: - binary-extensions: "npm:^2.0.0" - checksum: 10c0/a16eaee59ae2b315ba36fad5c5dcaf8e49c3e27318f8ab8fa3cdb8772bf559c8d1ba750a589c2ccb096113bb64497084361a25960899cb6172a6925ab6123d38 - languageName: node - linkType: hard - -"is-error@npm:^2.2.2": - version: 2.2.2 - resolution: "is-error@npm:2.2.2" - checksum: 10c0/475d3463968bf16e94485555d7cb7a879ed68685e08d365a3370972e626054f1846ebbb3934403091e06682445568601fe919e41646096e5007952d0c1f4fd9b - languageName: node - linkType: hard - -"is-extglob@npm:^2.1.1": - version: 2.1.1 - resolution: "is-extglob@npm:2.1.1" - checksum: 10c0/5487da35691fbc339700bbb2730430b07777a3c21b9ebaecb3072512dfd7b4ba78ac2381a87e8d78d20ea08affb3f1971b4af629173a6bf435ff8a4c47747912 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^4.0.0": - version: 4.0.0 - resolution: "is-fullwidth-code-point@npm:4.0.0" - checksum: 10c0/df2a717e813567db0f659c306d61f2f804d480752526886954a2a3e2246c7745fd07a52b5fecf2b68caf0a6c79dcdace6166fdf29cc76ed9975cc334f0a018b8 - languageName: node - linkType: hard - -"is-glob@npm:^4.0.1, is-glob@npm:~4.0.1": - version: 4.0.3 - resolution: "is-glob@npm:4.0.3" - dependencies: - is-extglob: "npm:^2.1.1" - checksum: 10c0/17fb4014e22be3bbecea9b2e3a76e9e34ff645466be702f1693e8f1ee1adac84710d0be0bd9f967d6354036fd51ab7c2741d954d6e91dae6bb69714de92c197a - languageName: node - linkType: hard - -"is-lambda@npm:^1.0.1": - version: 1.0.1 - resolution: "is-lambda@npm:1.0.1" - checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d - languageName: node - linkType: hard - -"is-number@npm:^7.0.0": - version: 7.0.0 - resolution: "is-number@npm:7.0.0" - checksum: 10c0/b4686d0d3053146095ccd45346461bc8e53b80aeb7671cc52a4de02dbbf7dc0d1d2a986e2fe4ae206984b4d34ef37e8b795ebc4f4295c978373e6575e295d811 - languageName: node - linkType: hard - -"is-plain-obj@npm:^4.1.0": - version: 4.1.0 - resolution: "is-plain-obj@npm:4.1.0" - checksum: 10c0/32130d651d71d9564dc88ba7e6fda0e91a1010a3694648e9f4f47bb6080438140696d3e3e15c741411d712e47ac9edc1a8a9de1fe76f3487b0d90be06ac9975e - languageName: node - linkType: hard - -"is-plain-object@npm:^5.0.0": - version: 5.0.0 - resolution: "is-plain-object@npm:5.0.0" - checksum: 10c0/893e42bad832aae3511c71fd61c0bf61aa3a6d853061c62a307261842727d0d25f761ce9379f7ba7226d6179db2a3157efa918e7fe26360f3bf0842d9f28942c - languageName: node - linkType: hard - -"is-promise@npm:^4.0.0": - version: 4.0.0 - resolution: "is-promise@npm:4.0.0" - checksum: 10c0/ebd5c672d73db781ab33ccb155fb9969d6028e37414d609b115cc534654c91ccd061821d5b987eefaa97cf4c62f0b909bb2f04db88306de26e91bfe8ddc01503 - languageName: node - linkType: hard - -"is-stream@npm:^4.0.1": - version: 4.0.1 - resolution: "is-stream@npm:4.0.1" - checksum: 10c0/2706c7f19b851327ba374687bc4a3940805e14ca496dc672b9629e744d143b1ad9c6f1b162dece81c7bfbc0f83b32b61ccc19ad2e05aad2dd7af347408f60c7f - languageName: node - linkType: hard - -"is-unicode-supported@npm:^1.2.0": - version: 1.3.0 - resolution: "is-unicode-supported@npm:1.3.0" - checksum: 10c0/b8674ea95d869f6faabddc6a484767207058b91aea0250803cbf1221345cb0c56f466d4ecea375dc77f6633d248d33c47bd296fb8f4cdba0b4edba8917e83d8a - languageName: node - linkType: hard - -"is-unicode-supported@npm:^2.0.0": - version: 2.1.0 - resolution: "is-unicode-supported@npm:2.1.0" - checksum: 10c0/a0f53e9a7c1fdbcf2d2ef6e40d4736fdffff1c9f8944c75e15425118ff3610172c87bf7bc6c34d3903b04be59790bb2212ddbe21ee65b5a97030fc50370545a5 - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - -"js-string-escape@npm:^1.0.1": - version: 1.0.1 - resolution: "js-string-escape@npm:1.0.1" - checksum: 10c0/2c33b9ff1ba6b84681c51ca0997e7d5a1639813c95d5b61cb7ad47e55cc28fa4a0b1935c3d218710d8e6bcee5d0cd8c44755231e3a4e45fc604534d9595a3628 - languageName: node - linkType: hard - -"js-yaml@npm:^3.14.1": - version: 3.14.1 - resolution: "js-yaml@npm:3.14.1" - dependencies: - argparse: "npm:^1.0.7" - esprima: "npm:^4.0.0" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/6746baaaeac312c4db8e75fa22331d9a04cccb7792d126ed8ce6a0bbcfef0cedaddd0c5098fade53db067c09fe00aa1c957674b4765610a8b06a5a189e46433b - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 - languageName: node - linkType: hard - -"load-json-file@npm:^7.0.0": - version: 7.0.1 - resolution: "load-json-file@npm:7.0.1" - checksum: 10c0/7117459608a0b6329c7f78e6e1f541b3162dd901c29dd5af721fec8b270177d2e3d7999c971f344fff04daac368d052732e2c7146014bc84d15e0b636975e19a - languageName: node - linkType: hard - -"locate-path@npm:^7.1.0": - version: 7.2.0 - resolution: "locate-path@npm:7.2.0" - dependencies: - p-locate: "npm:^6.0.0" - checksum: 10c0/139e8a7fe11cfbd7f20db03923cacfa5db9e14fa14887ea121345597472b4a63c1a42a8a5187defeeff6acf98fd568da7382aa39682d38f0af27433953a97751 - languageName: node - linkType: hard - -"lodash@npm:^4.17.15": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb - languageName: node - linkType: hard - -"make-fetch-happen@npm:^13.0.0": - version: 13.0.1 - resolution: "make-fetch-happen@npm:13.0.1" - dependencies: - "@npmcli/agent": "npm:^2.0.0" - cacache: "npm:^18.0.0" - http-cache-semantics: "npm:^4.1.1" - is-lambda: "npm:^1.0.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^3.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^0.6.3" - proc-log: "npm:^4.2.0" - promise-retry: "npm:^2.0.1" - ssri: "npm:^10.0.0" - checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e - languageName: node - linkType: hard - -"map-age-cleaner@npm:^0.1.3": - version: 0.1.3 - resolution: "map-age-cleaner@npm:0.1.3" - dependencies: - p-defer: "npm:^1.0.0" - checksum: 10c0/7495236c7b0950956c144fd8b4bc6399d4e78072a8840a4232fe1c4faccbb5eb5d842e5c0a56a60afc36d723f315c1c672325ca03c1b328650f7fcc478f385fd - languageName: node - linkType: hard - -"matcher@npm:^5.0.0": - version: 5.0.0 - resolution: "matcher@npm:5.0.0" - dependencies: - escape-string-regexp: "npm:^5.0.0" - checksum: 10c0/eda5471fc9d5b7264d63c81727824adc3585ddb5cfdc5fce5a9b7c86f946ff181610735d330b1c37a84811df872d1290bf4e9401d2be2a414204343701144b18 - languageName: node - linkType: hard - -"md5-hex@npm:^3.0.1": - version: 3.0.1 - resolution: "md5-hex@npm:3.0.1" - dependencies: - blueimp-md5: "npm:^2.10.0" - checksum: 10c0/ee2b4d8da16b527b3a3fe4d7a96720f43afd07b46a82d49421208b5a126235fb75cfb30b80d4029514772c8844273f940bddfbf4155c787f968f3be4060d01e4 - languageName: node - linkType: hard - -"mem@npm:^9.0.2": - version: 9.0.2 - resolution: "mem@npm:9.0.2" - dependencies: - map-age-cleaner: "npm:^0.1.3" - mimic-fn: "npm:^4.0.0" - checksum: 10c0/c2c56141399e520d8f0e50186bb7e4b49300b33984dc919682f3f13e53dec0e6608fbd327d5ae99494f45061a3a05a8ee04ccba6dcf795c3c215b5aa906eb41f - languageName: node - linkType: hard - -"merge2@npm:^1.3.0, merge2@npm:^1.4.1": - version: 1.4.1 - resolution: "merge2@npm:1.4.1" - checksum: 10c0/254a8a4605b58f450308fc474c82ac9a094848081bf4c06778200207820e5193726dc563a0d2c16468810516a5c97d9d3ea0ca6585d23c58ccfff2403e8dbbeb - languageName: node - linkType: hard - -"micromatch@npm:^4.0.4": - version: 4.0.8 - resolution: "micromatch@npm:4.0.8" - dependencies: - braces: "npm:^3.0.3" - picomatch: "npm:^2.3.1" - checksum: 10c0/166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8 - languageName: node - linkType: hard - -"mimic-fn@npm:^4.0.0": - version: 4.0.0 - resolution: "mimic-fn@npm:4.0.0" - checksum: 10c0/de9cc32be9996fd941e512248338e43407f63f6d497abe8441fa33447d922e927de54d4cc3c1a3c6d652857acd770389d5a3823f311a744132760ce2be15ccbf - languageName: node - linkType: hard - -"mimic-response@npm:^3.1.0": - version: 3.1.0 - resolution: "mimic-response@npm:3.1.0" - checksum: 10c0/0d6f07ce6e03e9e4445bee655202153bdb8a98d67ee8dc965ac140900d7a2688343e6b4c9a72cfc9ef2f7944dfd76eef4ab2482eb7b293a68b84916bac735362 - languageName: node - linkType: hard - -"minimatch@npm:^9.0.4": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed - languageName: node - linkType: hard - -"minimist@npm:^1.2.0, minimist@npm:^1.2.3": - version: 1.2.8 - resolution: "minimist@npm:1.2.8" - checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^3.0.0": - version: 3.0.5 - resolution: "minipass-fetch@npm:3.0.5" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^2.1.2" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": - version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 - languageName: node - linkType: hard - -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" - dependencies: - minipass: "npm:^3.0.0" - yallist: "npm:^4.0.0" - checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 - languageName: node - linkType: hard - -"mkdirp-classic@npm:^0.5.2, mkdirp-classic@npm:^0.5.3": - version: 0.5.3 - resolution: "mkdirp-classic@npm:0.5.3" - checksum: 10c0/95371d831d196960ddc3833cc6907e6b8f67ac5501a6582f47dfae5eb0f092e9f8ce88e0d83afcae95d6e2b61a01741ba03714eeafb6f7a6e9dcc158ac85b168 - languageName: node - linkType: hard - -"mkdirp@npm:^1.0.3": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" - bin: - mkdirp: bin/cmd.js - checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf - languageName: node - linkType: hard - -"ms@npm:^2.1.3": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 - languageName: node - linkType: hard - -"napi-build-utils@npm:^1.0.1": - version: 1.0.2 - resolution: "napi-build-utils@npm:1.0.2" - checksum: 10c0/37fd2cd0ff2ad20073ce78d83fd718a740d568b225924e753ae51cb69d68f330c80544d487e5e5bd18e28702ed2ca469c2424ad948becd1862c1b0209542b2e9 - languageName: node - linkType: hard - -"negotiator@npm:^0.6.3": - version: 0.6.3 - resolution: "negotiator@npm:0.6.3" - checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 - languageName: node - linkType: hard - -"node-abi@npm:^3.3.0": - version: 3.67.0 - resolution: "node-abi@npm:3.67.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/72ce2edbdfb84745bc201a4e48aa7146fd88a0d2c80046b6b17f28439c9a7683eab846f40f1e819349c31f7d9331ed5c50d1e741208d938dd5f38b29cab2275e - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 10.2.0 - resolution: "node-gyp@npm:10.2.0" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - glob: "npm:^10.3.10" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^13.0.0" - nopt: "npm:^7.0.0" - proc-log: "npm:^4.1.0" - semver: "npm:^7.3.5" - tar: "npm:^6.2.1" - which: "npm:^4.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/00630d67dbd09a45aee0a5d55c05e3916ca9e6d427ee4f7bc392d2d3dc5fad7449b21fc098dd38260a53d9dcc9c879b36704a1994235d4707e7271af7e9a835b - languageName: node - linkType: hard - -"nofilter@npm:^3.1.0": - version: 3.1.0 - resolution: "nofilter@npm:3.1.0" - checksum: 10c0/92459f3864a067b347032263f0b536223cbfc98153913b5dce350cb39c8470bc1813366e41993f22c33cc6400c0f392aa324a4b51e24c22040635c1cdb046499 - languageName: node - linkType: hard - -"nopt@npm:^7.0.0": - version: 7.2.1 - resolution: "nopt@npm:7.2.1" - dependencies: - abbrev: "npm:^2.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 - languageName: node - linkType: hard - -"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": - version: 3.0.0 - resolution: "normalize-path@npm:3.0.0" - checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 - languageName: node - linkType: hard - -"npm-run-path@npm:^6.0.0": - version: 6.0.0 - resolution: "npm-run-path@npm:6.0.0" - dependencies: - path-key: "npm:^4.0.0" - unicorn-magic: "npm:^0.3.0" - checksum: 10c0/b223c8a0dcd608abf95363ea5c3c0ccc3cd877daf0102eaf1b0f2390d6858d8337fbb7c443af2403b067a7d2c116d10691ecd22ab3c5273c44da1ff8d07753bd - languageName: node - linkType: hard - -"once@npm:^1.3.1, once@npm:^1.4.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: "npm:1" - checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 - languageName: node - linkType: hard - -"p-defer@npm:^1.0.0": - version: 1.0.0 - resolution: "p-defer@npm:1.0.0" - checksum: 10c0/ed603c3790e74b061ac2cb07eb6e65802cf58dce0fbee646c113a7b71edb711101329ad38f99e462bd2e343a74f6e9366b496a35f1d766c187084d3109900487 - languageName: node - linkType: hard - -"p-event@npm:^5.0.1": - version: 5.0.1 - resolution: "p-event@npm:5.0.1" - dependencies: - p-timeout: "npm:^5.0.2" - checksum: 10c0/2317171489537f316661fa863f3bb711b2ceb89182937238422cec10223cbb958c432d6c26a238446a622d788187bdd295b1d8ecedbe2e467e045930d60202b0 - languageName: node - linkType: hard - -"p-limit@npm:^4.0.0": - version: 4.0.0 - resolution: "p-limit@npm:4.0.0" - dependencies: - yocto-queue: "npm:^1.0.0" - checksum: 10c0/a56af34a77f8df2ff61ddfb29431044557fcbcb7642d5a3233143ebba805fc7306ac1d448de724352861cb99de934bc9ab74f0d16fe6a5460bdbdf938de875ad - languageName: node - linkType: hard - -"p-locate@npm:^6.0.0": - version: 6.0.0 - resolution: "p-locate@npm:6.0.0" - dependencies: - p-limit: "npm:^4.0.0" - checksum: 10c0/d72fa2f41adce59c198270aa4d3c832536c87a1806e0f69dffb7c1a7ca998fb053915ca833d90f166a8c082d3859eabfed95f01698a3214c20df6bb8de046312 - languageName: node - linkType: hard - -"p-map@npm:^4.0.0": - version: 4.0.0 - resolution: "p-map@npm:4.0.0" - dependencies: - aggregate-error: "npm:^3.0.0" - checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 - languageName: node - linkType: hard - -"p-map@npm:^5.5.0": - version: 5.5.0 - resolution: "p-map@npm:5.5.0" - dependencies: - aggregate-error: "npm:^4.0.0" - checksum: 10c0/410bce846b1e3db6bb2ccab6248372ecf4e635fc2b31331c8f56478e73fec9e146e8b4547585e635703160a3d252a6a65b8f855834aebc2c3408eb5789630cc4 - languageName: node - linkType: hard - -"p-timeout@npm:^5.0.2": - version: 5.1.0 - resolution: "p-timeout@npm:5.1.0" - checksum: 10c0/1b026cf9d5878c64bec4341ca9cda8ec6b8b3aea8a57885ca0fe2b35753a20d767fb6f9d3aa41e1252f42bc95432c05ea33b6b18f271fb10bfb0789591850a41 - languageName: node - linkType: hard - -"package-json-from-dist@npm:^1.0.0": - version: 1.0.0 - resolution: "package-json-from-dist@npm:1.0.0" - checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033 - languageName: node - linkType: hard - -"parse-ms@npm:^3.0.0": - version: 3.0.0 - resolution: "parse-ms@npm:3.0.0" - checksum: 10c0/056b4a32a9d3749f3f4cfffefb45c45540491deaa8e1d8ad43c2ddde7ba04edd076bd1b298f521238bb5fb084a9b2c4a2ebb78aefa651afbc4c2b0af4232fc54 - languageName: node - linkType: hard - -"parse-ms@npm:^4.0.0": - version: 4.0.0 - resolution: "parse-ms@npm:4.0.0" - checksum: 10c0/a7900f4f1ebac24cbf5e9708c16fb2fd482517fad353aecd7aefb8c2ba2f85ce017913ccb8925d231770404780df46244ea6fec598b3bde6490882358b4d2d16 - languageName: node - linkType: hard - -"path-exists@npm:^5.0.0": - version: 5.0.0 - resolution: "path-exists@npm:5.0.0" - checksum: 10c0/b170f3060b31604cde93eefdb7392b89d832dfbc1bed717c9718cbe0f230c1669b7e75f87e19901da2250b84d092989a0f9e44d2ef41deb09aa3ad28e691a40a - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-key@npm:^4.0.0": - version: 4.0.0 - resolution: "path-key@npm:4.0.0" - checksum: 10c0/794efeef32863a65ac312f3c0b0a99f921f3e827ff63afa5cb09a377e202c262b671f7b3832a4e64731003fa94af0263713962d317b9887bd1e0c48a342efba3 - languageName: node - linkType: hard - -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - -"path-type@npm:^4.0.0": - version: 4.0.0 - resolution: "path-type@npm:4.0.0" - checksum: 10c0/666f6973f332f27581371efaf303fd6c272cc43c2057b37aa99e3643158c7e4b2626549555d88626e99ea9e046f82f32e41bbde5f1508547e9a11b149b52387c - languageName: node - linkType: hard - -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1": - version: 2.3.1 - resolution: "picomatch@npm:2.3.1" - checksum: 10c0/26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be - languageName: node - linkType: hard - -"pkg-conf@npm:^4.0.0": - version: 4.0.0 - resolution: "pkg-conf@npm:4.0.0" - dependencies: - find-up: "npm:^6.0.0" - load-json-file: "npm:^7.0.0" - checksum: 10c0/27d027609f27228edcde121f6f707b4ba1f5488e95e98f2e58652ae4e99792081bd1de67d591f4a0f05b02c0b66d745591d49f82041cbc8d41e2238ef5d73eb4 - languageName: node - linkType: hard - -"plur@npm:^5.1.0": - version: 5.1.0 - resolution: "plur@npm:5.1.0" - dependencies: - irregular-plurals: "npm:^3.3.0" - checksum: 10c0/26bb622b8545fcfd47bbf56fbcca66c08693708a232e403fa3589e00003c56c14231ac57c7588ca5db83ef4be1f61383402c4ea954000768f779f8aef6eb6da8 - languageName: node - linkType: hard - -"prebuild-install@npm:^7.1.1": - version: 7.1.2 - resolution: "prebuild-install@npm:7.1.2" - dependencies: - detect-libc: "npm:^2.0.0" - expand-template: "npm:^2.0.3" - github-from-package: "npm:0.0.0" - minimist: "npm:^1.2.3" - mkdirp-classic: "npm:^0.5.3" - napi-build-utils: "npm:^1.0.1" - node-abi: "npm:^3.3.0" - pump: "npm:^3.0.0" - rc: "npm:^1.2.7" - simple-get: "npm:^4.0.0" - tar-fs: "npm:^2.0.0" - tunnel-agent: "npm:^0.6.0" - bin: - prebuild-install: bin.js - checksum: 10c0/e64868ba9ef2068fd7264f5b03e5298a901e02a450acdb1f56258d88c09dea601eefdb3d1dfdff8513fdd230a92961712be0676192626a3b4d01ba154d48bdd3 - languageName: node - linkType: hard - -"pretty-ms@npm:^8.0.0": - version: 8.0.0 - resolution: "pretty-ms@npm:8.0.0" - dependencies: - parse-ms: "npm:^3.0.0" - checksum: 10c0/e960d633ecca45445cf5c6dffc0f5e4bef6744c92449ab0e8c6c704800675ab71e181c5e02ece5265e02137a33e313d3f3e355fbf8ea30b4b5b23de423329f8d - languageName: node - linkType: hard - -"pretty-ms@npm:^9.0.0": - version: 9.1.0 - resolution: "pretty-ms@npm:9.1.0" - dependencies: - parse-ms: "npm:^4.0.0" - checksum: 10c0/fd111aad8800a04dfd654e6016da69bdaa6fc6a4c280f8e727cffd8b5960558e94942f1a94d4aa6e4d179561a0fbb0366a9ebe0ccefbbb0f8ff853b129cdefb9 - languageName: node - linkType: hard - -"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": - version: 4.2.0 - resolution: "proc-log@npm:4.2.0" - checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"pump@npm:^3.0.0": - version: 3.0.2 - resolution: "pump@npm:3.0.2" - dependencies: - end-of-stream: "npm:^1.1.0" - once: "npm:^1.3.1" - checksum: 10c0/5ad655cb2a7738b4bcf6406b24ad0970d680649d996b55ad20d1be8e0c02394034e4c45ff7cd105d87f1e9b96a0e3d06fd28e11fae8875da26e7f7a8e2c9726f - languageName: node - linkType: hard - -"queue-microtask@npm:^1.2.2": - version: 1.2.3 - resolution: "queue-microtask@npm:1.2.3" - checksum: 10c0/900a93d3cdae3acd7d16f642c29a642aea32c2026446151f0778c62ac089d4b8e6c986811076e1ae180a694cedf077d453a11b58ff0a865629a4f82ab558e102 - languageName: node - linkType: hard - -"rc@npm:^1.2.7": - version: 1.2.8 - resolution: "rc@npm:1.2.8" - dependencies: - deep-extend: "npm:^0.6.0" - ini: "npm:~1.3.0" - minimist: "npm:^1.2.0" - strip-json-comments: "npm:~2.0.1" - bin: - rc: ./cli.js - checksum: 10c0/24a07653150f0d9ac7168e52943cc3cb4b7a22c0e43c7dff3219977c2fdca5a2760a304a029c20811a0e79d351f57d46c9bde216193a0f73978496afc2b85b15 - languageName: node - linkType: hard - -"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 - languageName: node - linkType: hard - -"readdirp@npm:~3.6.0": - version: 3.6.0 - resolution: "readdirp@npm:3.6.0" - dependencies: - picomatch: "npm:^2.2.1" - checksum: 10c0/6fa848cf63d1b82ab4e985f4cf72bd55b7dcfd8e0a376905804e48c3634b7e749170940ba77b32804d5fe93b3cc521aa95a8d7e7d725f830da6d93f3669ce66b - languageName: node - linkType: hard - -"require-directory@npm:^2.1.1": - version: 2.1.1 - resolution: "require-directory@npm:2.1.1" - checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 - languageName: node - linkType: hard - -"resolve-cwd@npm:^3.0.0": - version: 3.0.0 - resolution: "resolve-cwd@npm:3.0.0" - dependencies: - resolve-from: "npm:^5.0.0" - checksum: 10c0/e608a3ebd15356264653c32d7ecbc8fd702f94c6703ea4ac2fb81d9c359180cba0ae2e6b71faa446631ed6145454d5a56b227efc33a2d40638ac13f8beb20ee4 - languageName: node - linkType: hard - -"resolve-from@npm:^5.0.0": - version: 5.0.0 - resolution: "resolve-from@npm:5.0.0" - checksum: 10c0/b21cb7f1fb746de8107b9febab60095187781137fd803e6a59a76d421444b1531b641bba5857f5dc011974d8a5c635d61cec49e6bd3b7fc20e01f0fafc4efbf2 - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: 10c0/c19ef26e4e188f408922c46f7ff480d38e8dfc55d448310dfb518736b23ed2c4f547fb64a6ed5bdba92cd7e7ddc889d36ff78f794816d5e71498d645ef476107 - languageName: node - linkType: hard - -"root-workspace-0b6124@workspace:.": - version: 0.0.0-use.local - resolution: "root-workspace-0b6124@workspace:." - dependencies: - "@agoric/synthetic-chain": "npm:^0.3.0" - ava: "npm:^5.3.1" - languageName: unknown - linkType: soft - -"run-parallel@npm:^1.1.9": - version: 1.2.0 - resolution: "run-parallel@npm:1.2.0" - dependencies: - queue-microtask: "npm:^1.2.2" - checksum: 10c0/200b5ab25b5b8b7113f9901bfe3afc347e19bb7475b267d55ad0eb86a62a46d77510cb0f232507c9e5d497ebda569a08a9867d0d14f57a82ad5564d991588b39 - languageName: node - linkType: hard - -"safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"semver@npm:^7.3.2, semver@npm:^7.3.5": - version: 7.6.3 - resolution: "semver@npm:7.6.3" - bin: - semver: bin/semver.js - checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf - languageName: node - linkType: hard - -"serialize-error@npm:^7.0.1": - version: 7.0.1 - resolution: "serialize-error@npm:7.0.1" - dependencies: - type-fest: "npm:^0.13.1" - checksum: 10c0/7982937d578cd901276c8ab3e2c6ed8a4c174137730f1fb0402d005af209a0e84d04acc874e317c936724c7b5b26c7a96ff7e4b8d11a469f4924a4b0ea814c05 - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"simple-concat@npm:^1.0.0": - version: 1.0.1 - resolution: "simple-concat@npm:1.0.1" - checksum: 10c0/62f7508e674414008910b5397c1811941d457dfa0db4fd5aa7fa0409eb02c3609608dfcd7508cace75b3a0bf67a2a77990711e32cd213d2c76f4fd12ee86d776 - languageName: node - linkType: hard - -"simple-get@npm:^4.0.0": - version: 4.0.1 - resolution: "simple-get@npm:4.0.1" - dependencies: - decompress-response: "npm:^6.0.0" - once: "npm:^1.3.1" - simple-concat: "npm:^1.0.0" - checksum: 10c0/b0649a581dbca741babb960423248899203165769747142033479a7dc5e77d7b0fced0253c731cd57cf21e31e4d77c9157c3069f4448d558ebc96cf9e1eebcf0 - languageName: node - linkType: hard - -"slash@npm:^4.0.0": - version: 4.0.0 - resolution: "slash@npm:4.0.0" - checksum: 10c0/b522ca75d80d107fd30d29df0549a7b2537c83c4c4ecd12cd7d4ea6c8aaca2ab17ada002e7a1d78a9d736a0261509f26ea5b489082ee443a3a810586ef8eff18 - languageName: node - linkType: hard - -"slice-ansi@npm:^5.0.0": - version: 5.0.0 - resolution: "slice-ansi@npm:5.0.0" - dependencies: - ansi-styles: "npm:^6.0.0" - is-fullwidth-code-point: "npm:^4.0.0" - checksum: 10c0/2d4d40b2a9d5cf4e8caae3f698fe24ae31a4d778701724f578e984dcb485ec8c49f0c04dab59c401821e80fcdfe89cace9c66693b0244e40ec485d72e543914f - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.3": - version: 8.0.4 - resolution: "socks-proxy-agent@npm:8.0.4" - dependencies: - agent-base: "npm:^7.1.1" - debug: "npm:^4.3.4" - socks: "npm:^2.8.3" - checksum: 10c0/345593bb21b95b0508e63e703c84da11549f0a2657d6b4e3ee3612c312cb3a907eac10e53b23ede3557c6601d63252103494caa306b66560f43af7b98f53957a - languageName: node - linkType: hard - -"socks@npm:^2.8.3": - version: 2.8.3 - resolution: "socks@npm:2.8.3" - dependencies: - ip-address: "npm:^9.0.5" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec - languageName: node - linkType: hard - -"sprintf-js@npm:~1.0.2": - version: 1.0.3 - resolution: "sprintf-js@npm:1.0.3" - checksum: 10c0/ecadcfe4c771890140da5023d43e190b7566d9cf8b2d238600f31bec0fc653f328da4450eb04bd59a431771a8e9cc0e118f0aa3974b683a4981b4e07abc2a5bb - languageName: node - linkType: hard - -"ssri@npm:^10.0.0": - version: 10.0.6 - resolution: "ssri@npm:10.0.6" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 - languageName: node - linkType: hard - -"stack-utils@npm:^2.0.6": - version: 2.0.6 - resolution: "stack-utils@npm:2.0.6" - dependencies: - escape-string-regexp: "npm:^2.0.0" - checksum: 10c0/651c9f87667e077584bbe848acaecc6049bc71979f1e9a46c7b920cad4431c388df0f51b8ad7cfd6eed3db97a2878d0fc8b3122979439ea8bac29c61c95eec8a - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.0, string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"string_decoder@npm:^1.1.1": - version: 1.3.0 - resolution: "string_decoder@npm:1.3.0" - dependencies: - safe-buffer: "npm:~5.2.0" - checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - -"strip-final-newline@npm:^4.0.0": - version: 4.0.0 - resolution: "strip-final-newline@npm:4.0.0" - checksum: 10c0/b0cf2b62d597a1b0e3ebc42b88767f0a0d45601f89fd379a928a1812c8779440c81abba708082c946445af1d6b62d5f16e2a7cf4f30d9d6587b89425fae801ff - languageName: node - linkType: hard - -"strip-json-comments@npm:~2.0.1": - version: 2.0.1 - resolution: "strip-json-comments@npm:2.0.1" - checksum: 10c0/b509231cbdee45064ff4f9fd73609e2bcc4e84a4d508e9dd0f31f70356473fde18abfb5838c17d56fb236f5a06b102ef115438de0600b749e818a35fbbc48c43 - languageName: node - linkType: hard - -"supertap@npm:^3.0.1": - version: 3.0.1 - resolution: "supertap@npm:3.0.1" - dependencies: - indent-string: "npm:^5.0.0" - js-yaml: "npm:^3.14.1" - serialize-error: "npm:^7.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/8164674f2e280cab875f0fef5bb36c15553c13e29697ff92f4e0d6bc62149f0303a89eee47535413ed145ea72e14a24d065bab233059d48a499ec5ebb4566b0f - languageName: node - linkType: hard - -"tar-fs@npm:^2.0.0": - version: 2.1.1 - resolution: "tar-fs@npm:2.1.1" - dependencies: - chownr: "npm:^1.1.1" - mkdirp-classic: "npm:^0.5.2" - pump: "npm:^3.0.0" - tar-stream: "npm:^2.1.4" - checksum: 10c0/871d26a934bfb7beeae4c4d8a09689f530b565f79bd0cf489823ff0efa3705da01278160da10bb006d1a793fa0425cf316cec029b32a9159eacbeaff4965fb6d - languageName: node - linkType: hard - -"tar-stream@npm:^2.1.4": - version: 2.2.0 - resolution: "tar-stream@npm:2.2.0" - dependencies: - bl: "npm:^4.0.3" - end-of-stream: "npm:^1.4.1" - fs-constants: "npm:^1.0.0" - inherits: "npm:^2.0.3" - readable-stream: "npm:^3.1.1" - checksum: 10c0/2f4c910b3ee7196502e1ff015a7ba321ec6ea837667220d7bcb8d0852d51cb04b87f7ae471008a6fb8f5b1a1b5078f62f3a82d30c706f20ada1238ac797e7692 - languageName: node - linkType: hard - -"tar@npm:^6.1.11, tar@npm:^6.2.1": - version: 6.2.1 - resolution: "tar@npm:6.2.1" - dependencies: - chownr: "npm:^2.0.0" - fs-minipass: "npm:^2.0.0" - minipass: "npm:^5.0.0" - minizlib: "npm:^2.1.1" - mkdirp: "npm:^1.0.3" - yallist: "npm:^4.0.0" - checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 - languageName: node - linkType: hard - -"temp-dir@npm:^3.0.0": - version: 3.0.0 - resolution: "temp-dir@npm:3.0.0" - checksum: 10c0/a86978a400984cd5f315b77ebf3fe53bb58c61f192278cafcb1f3fb32d584a21dc8e08b93171d7874b7cc972234d3455c467306cc1bfc4524b622e5ad3bfd671 - languageName: node - linkType: hard - -"time-zone@npm:^1.0.0": - version: 1.0.0 - resolution: "time-zone@npm:1.0.0" - checksum: 10c0/d00ebd885039109011b6e2423ebbf225160927333c2ade6d833e9cc4676db20759f1f3855fafde00d1bd668c243a6aa68938ce71fe58aab0d514e820d59c1d81 - languageName: node - linkType: hard - -"to-regex-range@npm:^5.0.1": - version: 5.0.1 - resolution: "to-regex-range@npm:5.0.1" - dependencies: - is-number: "npm:^7.0.0" - checksum: 10c0/487988b0a19c654ff3e1961b87f471702e708fa8a8dd02a298ef16da7206692e8552a0250e8b3e8759270f62e9d8314616f6da274734d3b558b1fc7b7724e892 - languageName: node - linkType: hard - -"tunnel-agent@npm:^0.6.0": - version: 0.6.0 - resolution: "tunnel-agent@npm:0.6.0" - dependencies: - safe-buffer: "npm:^5.0.1" - checksum: 10c0/4c7a1b813e7beae66fdbf567a65ec6d46313643753d0beefb3c7973d66fcec3a1e7f39759f0a0b4465883499c6dc8b0750ab8b287399af2e583823e40410a17a - languageName: node - linkType: hard - -"type-fest@npm:^0.13.1": - version: 0.13.1 - resolution: "type-fest@npm:0.13.1" - checksum: 10c0/0c0fa07ae53d4e776cf4dac30d25ad799443e9eef9226f9fddbb69242db86b08584084a99885cfa5a9dfe4c063ebdc9aa7b69da348e735baede8d43f1aeae93b - languageName: node - linkType: hard - -"unicorn-magic@npm:^0.3.0": - version: 0.3.0 - resolution: "unicorn-magic@npm:0.3.0" - checksum: 10c0/0a32a997d6c15f1c2a077a15b1c4ca6f268d574cf5b8975e778bb98e6f8db4ef4e86dfcae4e158cd4c7e38fb4dd383b93b13eefddc7f178dea13d3ac8a603271 - languageName: node - linkType: hard - -"unique-filename@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-filename@npm:3.0.0" - dependencies: - unique-slug: "npm:^4.0.0" - checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f - languageName: node - linkType: hard - -"unique-slug@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-slug@npm:4.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 - languageName: node - linkType: hard - -"util-deprecate@npm:^1.0.1": - version: 1.0.2 - resolution: "util-deprecate@npm:1.0.2" - checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 - languageName: node - linkType: hard - -"well-known-symbols@npm:^2.0.0": - version: 2.0.0 - resolution: "well-known-symbols@npm:2.0.0" - checksum: 10c0/cb6c12e98877e8952ec28d13ae6f4fdb54ae1cb49b16a728720276dadd76c930e6cb0e174af3a4620054dd2752546f842540122920c6e31410208abd4958ee6b - languageName: node - linkType: hard - -"which@npm:^2.0.1": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^4.0.0": - version: 4.0.0 - resolution: "which@npm:4.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 - languageName: node - linkType: hard - -"write-file-atomic@npm:^5.0.1": - version: 5.0.1 - resolution: "write-file-atomic@npm:5.0.1" - dependencies: - imurmurhash: "npm:^0.1.4" - signal-exit: "npm:^4.0.1" - checksum: 10c0/e8c850a8e3e74eeadadb8ad23c9d9d63e4e792bd10f4836ed74189ef6e996763959f1249c5650e232f3c77c11169d239cbfc8342fc70f3fe401407d23810505d - languageName: node - linkType: hard - -"y18n@npm:^5.0.5": - version: 5.0.8 - resolution: "y18n@npm:5.0.8" - checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yargs-parser@npm:^21.1.1": - version: 21.1.1 - resolution: "yargs-parser@npm:21.1.1" - checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 - languageName: node - linkType: hard - -"yargs@npm:^17.7.2": - version: 17.7.2 - resolution: "yargs@npm:17.7.2" - dependencies: - cliui: "npm:^8.0.1" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.3" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^21.1.1" - checksum: 10c0/ccd7e723e61ad5965fffbb791366db689572b80cca80e0f96aad968dfff4156cd7cd1ad18607afe1046d8241e6fb2d6c08bf7fa7bfb5eaec818735d8feac8f05 - languageName: node - linkType: hard - -"yocto-queue@npm:^1.0.0": - version: 1.1.1 - resolution: "yocto-queue@npm:1.1.1" - checksum: 10c0/cb287fe5e6acfa82690acb43c283de34e945c571a78a939774f6eaba7c285bacdf6c90fbc16ce530060863984c906d2b4c6ceb069c94d1e0a06d5f2b458e2a92 - languageName: node - linkType: hard - -"yoctocolors@npm:^2.0.0": - version: 2.1.1 - resolution: "yoctocolors@npm:2.1.1" - checksum: 10c0/85903f7fa96f1c70badee94789fade709f9d83dab2ec92753d612d84fcea6d34c772337a9f8914c6bed2f5fc03a428ac5d893e76fab636da5f1236ab725486d0 - languageName: node - linkType: hard diff --git a/a3p-integration/proposals/n:upgrade-next/.gitignore b/a3p-integration/proposals/n:upgrade-next/.gitignore index 10c30e2fde7..2f3ed03b169 100644 --- a/a3p-integration/proposals/n:upgrade-next/.gitignore +++ b/a3p-integration/proposals/n:upgrade-next/.gitignore @@ -5,3 +5,4 @@ upgrade-bank/ upgrade-provisionPool/ upgrade-orch-core/ replace-electorate/ +price-feeds/ diff --git a/a3p-integration/proposals/n:upgrade-next/agoric-tools.js b/a3p-integration/proposals/n:upgrade-next/agoric-tools.js index 205fe47df4f..9e69836862d 100644 --- a/a3p-integration/proposals/n:upgrade-next/agoric-tools.js +++ b/a3p-integration/proposals/n:upgrade-next/agoric-tools.js @@ -1,4 +1,10 @@ -import { queryVstorage } from '@agoric/synthetic-chain'; +import assert from 'node:assert'; +import { + queryVstorage, + agops, + agoric, + executeOffer, +} from '@agoric/synthetic-chain'; import { makeMarshal, Remotable } from '@endo/marshal'; export const GOV4ADDR = 'agoric1c9gyu460lu70rtcdp95vummd6032psmpdx7wdy'; @@ -31,3 +37,97 @@ export const queryVstorageFormatted = async (path, index = -1) => { const formattedDataAtIndex = JSON.parse(formattedData.values.at(index)); return marshaller.fromCapData(formattedDataAtIndex); }; + +export const generateVaultDirectorParamChange = async ( + previousOfferId, + voteDur, + params, + paramsPath, +) => { + const voteDurSec = BigInt(voteDur); + const toSec = ms => BigInt(Math.round(ms / 1000)); + + const id = `propose-${Date.now()}`; + const deadline = toSec(Date.now()) + voteDurSec; + + const zip = (xs, ys) => xs.map((x, i) => [x, ys[i]]); + // KLUDGE: partial deconstruction of smallCaps values + const fromSmallCapsEntries = txt => { + const { body, slots } = JSON.parse(txt); + const theEntries = zip(JSON.parse(body.slice(1)), slots).map( + ([[name, ref], boardID]) => { + const iface = ref.replace(/^\$\d+\./, ''); + return [name, { iface, boardID }]; + }, + ); + return Object.fromEntries(theEntries); + }; + + const slots = []; // XXX global mutable state + const smallCaps = { + Nat: n => `+${n}`, + // XXX mutates obj + ref: obj => { + if (obj.ix) return obj.ix; + const ix = slots.length; + slots.push(obj.boardID); + obj.ix = `$${ix}.Alleged: ${obj.iface}`; + return obj.ix; + }, + }; + + await null; + const instance = fromSmallCapsEntries( + await agoric.follow('-lF', ':published.agoricNames.instance', '-o', 'text'), + ); + assert(instance.VaultFactory); + + const body = { + method: 'executeOffer', + offer: { + id, + invitationSpec: { + invitationMakerName: 'VoteOnParamChange', + previousOffer: previousOfferId, + source: 'continuing', + }, + offerArgs: { + deadline: smallCaps.Nat(deadline), + instance: smallCaps.ref(instance.VaultFactory), + params, + path: paramsPath, + }, + proposal: {}, + }, + }; + + const capData = { body: `#${JSON.stringify(body)}`, slots }; + return JSON.stringify(capData); +}; + +export const proposeVaultDirectorParamChange = async ( + address, + params, + path, +) => { + const charterAcceptOfferId = await agops.ec( + 'find-continuing-id', + '--for', + `${'charter\\ member\\ invitation'}`, + '--from', + address, + ); + + return executeOffer( + address, + generateVaultDirectorParamChange(charterAcceptOfferId, 30, params, path), + ); +}; + +export const voteForNewParams = (accounts, position) => { + return Promise.all( + accounts.map(account => + agops.ec('vote', '--forPosition', position, '--send-from', account), + ), + ); +}; diff --git a/a3p-integration/proposals/f:replace-price-feeds/eval.sh b/a3p-integration/proposals/n:upgrade-next/eval.sh similarity index 100% rename from a3p-integration/proposals/f:replace-price-feeds/eval.sh rename to a3p-integration/proposals/n:upgrade-next/eval.sh diff --git a/a3p-integration/proposals/n:upgrade-next/package.json b/a3p-integration/proposals/n:upgrade-next/package.json index 465160effb6..e2914aa6253 100644 --- a/a3p-integration/proposals/n:upgrade-next/package.json +++ b/a3p-integration/proposals/n:upgrade-next/package.json @@ -12,7 +12,16 @@ "vats/upgrade-provisionPool.js upgrade-provisionPool", "testing/add-LEMONS.js add-LEMONS", "testing/add-OLIVES.js add-OLIVES", - "inter-protocol/replace-electorate-core.js replace-electorate A3P_INTEGRATION" + "inter-protocol/replace-electorate-core.js replace-electorate A3P_INTEGRATION", + "inter-protocol/updatePriceFeeds.js price-feeds A3P_INTEGRATION", + "vats/add-auction.js price-feeds", + "vats/upgradeVaults.js price-feeds", + "inter-protocol/updatePriceFeeds.js submission/main main", + "vats/add-auction.js submission/main", + "vats/upgradeVaults.js submission/main", + "inter-protocol/updatePriceFeeds.js submission/devnet devnet", + "vats/add-auction.js submission/devnet", + "vats/upgradeVaults.js submission/devnet" ], "type": "Software Upgrade Proposal" }, diff --git a/a3p-integration/proposals/f:replace-price-feeds/priceFeedUpdate.test.js b/a3p-integration/proposals/n:upgrade-next/priceFeedUpdate.test.js similarity index 100% rename from a3p-integration/proposals/f:replace-price-feeds/priceFeedUpdate.test.js rename to a3p-integration/proposals/n:upgrade-next/priceFeedUpdate.test.js diff --git a/a3p-integration/proposals/f:replace-price-feeds/resetChargingPeriod.js b/a3p-integration/proposals/n:upgrade-next/resetChargingPeriod.js similarity index 100% rename from a3p-integration/proposals/f:replace-price-feeds/resetChargingPeriod.js rename to a3p-integration/proposals/n:upgrade-next/resetChargingPeriod.js diff --git a/a3p-integration/proposals/n:upgrade-next/test.sh b/a3p-integration/proposals/n:upgrade-next/test.sh index 56492d366f6..07c0eb0d035 100755 --- a/a3p-integration/proposals/n:upgrade-next/test.sh +++ b/a3p-integration/proposals/n:upgrade-next/test.sh @@ -3,6 +3,7 @@ # Place here any test that should be executed using the executed proposal. # The effects of this step are not persisted in further proposal layers. +# suppress file names from glob that run earlier GLOBIGNORE=initial.test.js yarn ava ./replaceElectorate.test.js @@ -10,5 +11,5 @@ yarn ava ./replaceElectorate.test.js # test the state right after upgrade yarn ava initial.test.js -# test more, in ways that changes system state +# test more, in ways that change system state yarn ava ./*.test.js diff --git a/golang/cosmos/app/upgrade.go b/golang/cosmos/app/upgrade.go index e5c2fa97a98..4b5565045c0 100644 --- a/golang/cosmos/app/upgrade.go +++ b/golang/cosmos/app/upgrade.go @@ -105,19 +105,24 @@ func buildProposalStepWithArgs(moduleName string, entrypoint string, opts map[st return vm.CoreProposalStepForModules(proposal), nil } -func replaceElectorateCoreProposalStep(upgradeName string) (vm.CoreProposalStep, error) { - var variant string - - switch validUpgradeName(upgradeName) { - case "UNRELEASED_A3P_INTEGRATION": - variant = "A3P_INTEGRATION" - case "UNRELEASED_main": - variant = "MAINNET" - case "UNRELEASED_devnet": - variant = "DEVNET" +func getVariantFromUpgradeName(upgradeName string) string { + switch upgradeName { + case "UNRELEASED_A3P_INTEGRATION": + return "A3P_INTEGRATION" + case "UNRELEASED_main": + return "MAINNET" + case "UNRELEASED_devnet": + return "DEVNET" // Noupgrade for this version. - case "UNRELEASED_BASIC": - } + case "UNRELEASED_BASIC": + return "" + default: + return "" + } +} + +func replaceElectorateCoreProposalStep(upgradeName string) (vm.CoreProposalStep, error) { + variant := getVariantFromUpgradeName(upgradeName) return buildProposalStepWithArgs( "@agoric/builders/scripts/inter-protocol/replace-electorate-core.js", @@ -128,6 +133,18 @@ func replaceElectorateCoreProposalStep(upgradeName string) (vm.CoreProposalStep, ) } +func replacePriceFeedsCoreProposal(upgradeName string) (vm.CoreProposalStep, error) { + variant := getVariantFromUpgradeName(upgradeName) + + return buildProposalStepWithArgs( + "@agoric/builders/scripts/inter-protocol/updatePriceFeeds.js", + "defaultProposalBuilder", + map[string]any{ + "variant": variant, + }, + ) +} + // unreleasedUpgradeHandler performs standard upgrade actions plus custom actions for the unreleased upgrade. func unreleasedUpgradeHandler(app *GaiaApp, targetUpgrade string) func(sdk.Context, upgradetypes.Plan, module.VersionMap) (module.VersionMap, error) { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVm module.VersionMap) (module.VersionMap, error) { @@ -150,10 +167,22 @@ func unreleasedUpgradeHandler(app *GaiaApp, targetUpgrade string) func(sdk.Conte return nil, err } + priceFeedUpdate, err := replacePriceFeedsCoreProposal(targetUpgrade) + if err != nil { + return nil, err + } + // Each CoreProposalStep runs sequentially, and can be constructed from // one or more modules executing in parallel within the step. CoreProposalSteps = []vm.CoreProposalStep{ replaceElectorateStep, + priceFeedUpdate, + vm.CoreProposalStepForModules( + "@agoric/builders/scripts/vats/add-auction.js", + ), + vm.CoreProposalStepForModules( + "@agoric/builders/scripts/vats/upgradeVaults.js", + ), vm.CoreProposalStepForModules( // Upgrade Zoe (no new ZCF needed). "@agoric/builders/scripts/vats/upgrade-zoe.js", @@ -162,18 +191,6 @@ func unreleasedUpgradeHandler(app *GaiaApp, targetUpgrade string) func(sdk.Conte vm.CoreProposalStepForModules( "@agoric/builders/scripts/vats/revive-kread.js", ), - vm.CoreProposalStepForModules( - // Upgrade to new liveslots for repaired vow usage. - "@agoric/builders/scripts/vats/upgrade-orch-core.js", - ), - vm.CoreProposalStepForModules( - // Upgrade to new liveslots and support vows. - "@agoric/builders/scripts/smart-wallet/build-wallet-factory2-upgrade.js", - ), - vm.CoreProposalStepForModules( - // Create vat-orchestration. - "@agoric/builders/scripts/vats/init-orchestration.js", - ), } } diff --git a/packages/SwingSet/docs/host-app.md b/packages/SwingSet/docs/host-app.md new file mode 100644 index 00000000000..581406c3907 --- /dev/null +++ b/packages/SwingSet/docs/host-app.md @@ -0,0 +1,61 @@ +# The Host Application + +SwingSet is a library that helps you write a "Host Application" around a kernel, which in turn manages some number of vats and devices. The Host Application does not come with SwingSet: you must write one specific to your particular application. + +## Host Application Responsibilities + +### State Management + +First, the host app is responsible for managing the kernel's state in a "SwingStore", using the `@agoric/swing-store` package, which is a SQLite database in some user-selected base directory, wrapped in useful APIs. A SwingStore is created by the `@agoric/swing-store` package, and consists of both a `hostStorage` facet and a `kernelStorage` facet. The `kernelStorage` facet must be given to `makeSwingsetController()`, the primary API for creating a kernel. All kernel state is kept inside the SwingStore. + +The host app must use `hostStorage.commit()` to commit the SwingStore changes after each group of device inputs and cranks (usually triggered with one or more calls to `controller.run()`). The host must not commit while the run is execution: it must wait for the `controller.run()` return Promise to settle first. + +### Device IO + +The host app is also responsible for all device input and output. The kernel itself cannot talk to the outside world, except through devices. These devices are configured with the kernel config record (along with static vats), but the device *endowments* are provided by the host app via the `deviceEndowments` argument to `makeSwingsetController()`. + +SwingSet provides robust and deterministic computation, even in the face of unexpected reboot, and avoids a failure mode called "hangover inconsistency" by following the lead of the Waterken and E systems. Output messages (in fact all communication with the outside world) must be embargoed until all consequences of an inbound delivery have been durably committed. To maintain this, device endowments must refrain from transmitting their outputs or modifying state outside of the DB until after the host app calls `hostStorage.commit()`, and they must be prepared to re-transmit their outputs or re-apply their effects if they awaken into a world where the durable state says that a message must be transmitted but no record of an acknowledgment is also recorded. See the comms subsystem, especially the "mailbox" device, for more details. + +### Kernel Upgrade + +The life cycle of a SwingSet kernel begins with the one and only call to `initializeSwingset()`, which populates the SwingStore DB for the first time. After that, the kernel is presumed to be immortal, but its execution is broken up into a series of reboots. Each reboot (e.g. each time the host application is started), the app must build a new controller with `makeSwingsetController()`, to have something to run. + +From time to time, the host app will be upgraded to use a newer version of the SwingSet kernel code (e.g. a new version of this `@agoric/swingset-vat` package). The newer version might require an upgrade to the kernel's persisted/durable state. For example, the way it represents some vat metadata might be made more efficient, and the upgrade process needs to examine and rewrite vat state to use the new representation. Or, a bug might be fixed, and the upgrade process needs to locate and remediate any consequences of the bug having been present during earlier execution. + +To make the resulting state changes occur deterministically, upgrades are not automatic. Instead, each time the host app reboots with a new version of the kernel code, it must call `upgradeSwingset(kernelStorage)`. It must do this *before* calling `makeSwingsetController()`, as that function will throw an error if given a SwingStore that has not been upgraded. + +It is safe to call `upgradeSwingset` on reboots that do not change the version of the kernel code: the function is idempotent, and will do nothing if the SwingStore is already up-to-date. + +Some upgrades (in particular bug remediations) need to add events to the kernel's run-queue. To avoid having these events be intermingled with work that might already be on the run-queue at reboot time (e.g. work leftover from previous runs), these events are not automatically injected at that time. Instead, the kernel remembers what needs to be done, and waits for the host to invoke `controller.injectQueuedUpgradeEvents()` at a time of their choosing. This should be done before the next `commit()`, to avoid the risk of them being lost by a reboot. + +So most host applications will start each reboot with a sequence like this: + +```js +const { hostStorage, kernelStorage } = openSwingStore(baseDirectory); +upgradeSwingset(kernelStorage); +const controller = makeSwingsetController(kernelStorage, deviceEndowments); +controller.injectQueuedUpgradeEvents(); +``` + +followed by later code to execute runs. Inputs can be fed all-at-once, or each processed in their own run, but at the end of the block, the host app must `commit()` the DB: + +```js +async function doBlock(deviceInputs) { + for (const input of deviceInputs) { + injectDeviceInput(input); + await controller.run(); + } + hostStorage.commit(); + emitDeviceOutputs(); +} +``` + +The actual signature of `upgradeSwingset` is `const { modified } = upgradeSwingset(kernelStorage)`, and the `modified` flag indicates whether anything actually got upgraded. Host applications which have other means to keep track of software upgrades may wish to assert that `modified === false` in reboots that are not associated with a change to the kernel package version. They can also safely skip the `injectQueuedUpgradeEvents` call if nothing was modified. + +### Crank Execution + +For convenience in discussion, we split execution into "blocks". During a block, the host may call one or more device inputs, such as inbound messages, or timer wakeup events. The end of the block is marked by one or more calls to `controller.run()`, followed by a `hostStorage.commit()`, followed by the host-provided device endowments doing whatever kind of outbound IO they need to do. + +In a replicated/blockchain host environment, these are the same blocks that make up the chain. Inbound messages come from the signed transactions that are included in each block. And each block can inform the timer device that time has advanced to whatever consensus time is computed as part of the blockchain voting process. "Outbound IO" is really just recording data in the chain state, where external parties can retrieve it and verify it against the block header and its hash. + +In a singular/solo environment, "block boundaries" are simply points in time when the host app decides it would be useful to perform computation, commit state, and release outbound messages. These "blocks" are triggered by inbound IO requests, or timer wakeup events. The host might choose to trigger a "block" immediately after each such event (to minimize latency), or it might defer execution for a little while to batch them together (for efficiency). diff --git a/packages/SwingSet/misc-tools/scan-9039-promises.js b/packages/SwingSet/misc-tools/scan-9039-promises.js new file mode 100644 index 00000000000..c847c2b55d3 --- /dev/null +++ b/packages/SwingSet/misc-tools/scan-9039-promises.js @@ -0,0 +1,158 @@ +#!/usr/bin/env node +// @ts-nocheck + +// Given a swingstore database, produce a list of vpid/vatID pairs for +// all promises that are resolved but still in the c-list of their +// formerly-deciding vat. This happens when a vat is upgraded and the +// kernel disconnects (rejects) the previous incarnation's outstanding +// promises (https://github.com/Agoric/agoric-sdk/issues/9039). + +import process from 'process'; +import fs from 'fs'; +import sqlite3 from 'better-sqlite3'; +import yargsParser from 'yargs-parser'; +import '@endo/init/debug.js'; + +const main = rawArgv => { + const { _: args, ...options } = yargsParser(rawArgv.slice(2)); + // console.log(args, options); + if (Reflect.ownKeys(options).length > 0 || args.length !== 1) { + console.error( + [ + `Usage: ${rawArgv[1]} /path/to/swingstore.sqlite`, + 'Find leftover promises for bug #9039.', + ].join('\n'), + ); + process.exitCode = 1; + return; + } + + const [ssDBPath] = args; + if (!fs.existsSync(ssDBPath)) { + throw Error(`swingstore DB path (${ssDBPath}) must exist`); + } + const ssDB = sqlite3(/** @type {string} */ (ssDBPath)); + let queries = 0; + + const sqlGet = ssDB.prepare('SELECT value FROM kvStore WHERE key=?').pluck(); + const realRawGet = key => { + queries += 1; + return sqlGet.get(key); + }; + const realGet = key => JSON.parse(realRawGet(key)); + + // fake database for testing + const fake = { + 'vat.names': ['bootstrap'], + 'vat.name.bootstrap': 'v1', + 'vat.dynamicIDs': ['v9'], + runQueue: [10, 10], + 'runQueue.10': { type: 'notify', vatID: 'v9', kpid: 'kp1005304' }, + 'kp1005304.data.body': + '#{"incarnationNumber":0,"name":"vatUpgraded","upgradeMessage":"vat upgraded"}', + 'kp1005304.data.slots': [], + 'kp1005304.refCount': 1, + 'kp1005304.state': 'rejected', + }; + const fakeRawGet = key => { + queries += 1; + return fake[key]; + }; + // eslint-disable-next-line no-unused-vars + const fakeGet = key => fakeRawGet(key); + + // const [get, rawGet] = [fakeGet, fakeRawGet]; + const [get, rawGet] = [realGet, realRawGet]; + + const vatNames = get('vat.names'); + const staticIDs = vatNames.map(name => rawGet(`vat.name.${name}`)); + const dynamicIDs = get('vat.dynamicIDs'); + const allVatIDs = [...staticIDs, ...dynamicIDs]; + // console.log(allVatIDs); + + const sqlRange = ssDB.prepare( + `SELECT * FROM kvStore WHERE key >= ? AND key < ?`, + ); + + // old way took 547472 queries + // const rejectedKPIDs = new Set(); + + const [head, tail] = get('runQueue'); + const notifies = new Map(); // .get(kpid) = [vatIDs..]; + for (let p = head; p < tail; p += 1) { + const rq = get(`runQueue.${p}`); + if (rq.type === 'notify') { + const { vatID, kpid } = rq; + if (!notifies.has(kpid)) { + notifies.set(kpid, []); + } + notifies.get(kpid).push(vatID); + } + } + console.log(`pending notifies:`, notifies); + + const rejectedKPIDs = new Set(); + const nonRejectedKPIDs = new Set(); + + const isRejected = kpid => { + if (nonRejectedKPIDs.has(kpid)) { + return false; + } + if (rejectedKPIDs.has(kpid)) { + return true; + } + const state = rawGet(`${kpid}.state`); + // missing state means the kpid is deleted somehow, shouldn't happen + assert(state, `${kpid}.state is missing`); + if (state === 'rejected') { + rejectedKPIDs.add(kpid); + return true; + } + nonRejectedKPIDs.add(kpid); + return false; + }; + + // Bug 9039 causes the kernel to reject/disconnect a promise on + // behalf of the upgraded vat, but not remove it from the vat's + // c-list (which would normally happen when the vat emitted a + // syscall.resolve). The rejection process erases the `.decider` + // record, so we no longer know which vat to look at. We're looking + // for vpids which are 1: rejected, 2: present in a vat c-list, 3: + // do *not* have a notify scheduled. + + const buggyKPIDs = []; // tuples of [kpid, vatID] + const involvedVats = {}; + + for (const vatID of allVatIDs) { + // TODO: skip vats in vats.terminated, belt-and-suspenders + const prefix = `${vatID}.c.`; + const len = prefix.length; + const k1 = `${prefix}kp`; + const k2 = `${prefix}kq`; + for (const row of sqlRange.iterate(k1, k2)) { + // the kvStore's actual API (getNextKey) requires one query per result + queries += 1; + const kpid = row.key.slice(len); + if (!isRejected(kpid)) { + continue; + } + const n = notifies.get(kpid); + if (!n || !n.includes(vatID)) { + // there is no pending notify + buggyKPIDs.push([kpid, vatID]); + involvedVats[vatID] = 1 + (involvedVats[vatID] || 0); + } + } + } + + // console.log(buggyKPIDs); + console.log(`scan 9039: ${buggyKPIDs.length} kpid/vatID pairs to clean up`); + console.log(`first is:`, buggyKPIDs[0]); + console.log( + `${Reflect.ownKeys(involvedVats).length} vats involved:`, + involvedVats, + ); + console.log(`${queries} DB queries`); +}; + +main(process.argv); diff --git a/packages/SwingSet/src/controller/controller.js b/packages/SwingSet/src/controller/controller.js index 3321d1f92a6..c3091989814 100644 --- a/packages/SwingSet/src/controller/controller.js +++ b/packages/SwingSet/src/controller/controller.js @@ -366,6 +366,10 @@ export async function makeSwingsetController( return kref; }, + kpRegisterInterest(kpid) { + return kernel.kpRegisterInterest(kpid); + }, + kpStatus(kpid) { return kernel.kpStatus(kpid); }, @@ -384,6 +388,8 @@ export async function makeSwingsetController( return kernel.deviceNameToID(deviceName); }, + injectQueuedUpgradeEvents: () => kernel.injectQueuedUpgradeEvents(), + /** * Queue a method call into the named vat * diff --git a/packages/SwingSet/src/controller/upgradeSwingset.js b/packages/SwingSet/src/controller/upgradeSwingset.js index 87195b8cfae..3c12c97f0b6 100644 --- a/packages/SwingSet/src/controller/upgradeSwingset.js +++ b/packages/SwingSet/src/controller/upgradeSwingset.js @@ -1,9 +1,17 @@ +import { Fail } from '@endo/errors'; import { DEFAULT_REAP_DIRT_THRESHOLD_KEY, DEFAULT_GC_KREFS_PER_BOYD, getAllDynamicVats, getAllStaticVats, + incrementReferenceCount, + readQueue, } from '../kernel/state/kernelKeeper.js'; +import { enumeratePrefixedKeys } from '../kernel/state/storageHelper.js'; + +/** + * @import {RunQueueEvent} from '../types-internal.js'; + */ const upgradeVatV0toV1 = (kvStore, defaultReapDirtThreshold, vatID) => { // This is called, once per vat, when upgradeSwingset migrates from @@ -92,11 +100,13 @@ const upgradeVatV0toV1 = (kvStore, defaultReapDirtThreshold, vatID) => { * `hostStorage.commit()` afterwards. * * @param {SwingStoreKernelStorage} kernelStorage - * @returns {boolean} true if any changes were made + * @returns {{ modified: boolean }} */ export const upgradeSwingset = kernelStorage => { const { kvStore } = kernelStorage; let modified = false; + /** @type {RunQueueEvent[]} */ + const upgradeEvents = []; let vstring = kvStore.get('version'); if (vstring === undefined) { vstring = '0'; @@ -204,9 +214,129 @@ export const upgradeSwingset = kernelStorage => { version = 2; } + if (version < 3) { + // v3 means that we've completed remediation for bug #9039 + console.log(`Starting remediation of bug #9039`); + + // find all terminated vats + const terminated = new Set(JSON.parse(getRequired('vats.terminated'))); + + // find all live vats + const allVatIDs = []; + for (const [_name, vatID] of getAllStaticVats(kvStore)) { + if (!terminated.has(vatID)) { + allVatIDs.push(vatID); + } + } + for (const vatID of getAllDynamicVats(getRequired)) { + if (!terminated.has(vatID)) { + allVatIDs.push(vatID); + } + } + + // find all pending notifies + const notifies = new Map(); // .get(kpid) = [vatIDs..]; + for (const name of ['runQueue', 'acceptanceQueue']) { + for (const rq of readQueue(name, getRequired)) { + if (rq.type === 'notify') { + const { vatID, kpid } = rq; + assert(vatID); + assert(kpid); + let vats = notifies.get(kpid); + if (!vats) { + vats = []; + notifies.set(kpid, vats); + } + vats.push(vatID); + } + } + } + console.log(` - pending notifies:`, notifies); + + // cache of known-settled kpids: will grow to num(kpids) + const KPIDStatus = new Map(); + const isSettled = kpid => { + if (KPIDStatus.has(kpid)) { + return KPIDStatus.get(kpid); + } + const state = kvStore.get(`${kpid}.state`); + // missing state means the kpid is deleted somehow, shouldn't happen + state || Fail`${kpid}.state is missing`; + const settled = state !== 'unresolved'; + KPIDStatus.set(kpid, settled); + return settled; + }; + + // walk vNN.c.kpNN for all vats, for each one check the + // kpNN.state, for the settled ones check for a pending notify, + // record the ones without a pending notify + + const buggyKPIDs = []; // [kpid, vatID] + for (const vatID of allVatIDs) { + const prefix = `${vatID}.c.`; + const len = prefix.length; + const ckpPrefix = `${vatID}.c.kp`; + for (const key of enumeratePrefixedKeys(kvStore, ckpPrefix)) { + const kpid = key.slice(len); + if (isSettled(kpid)) { + const n = notifies.get(kpid); + if (!n || !n.includes(vatID)) { + // there is no pending notify + buggyKPIDs.push([kpid, vatID]); + } + } + } + } + console.log(` - found ${buggyKPIDs.length} buggy kpids, enqueueing fixes`); + + // now fix it. The bug means we failed to delete the c-list entry + // and decref it back when the promise was rejected. That decref + // would have pushed the kpid onto maybeFreeKrefs, which would + // have triggered a refcount check at end-of-crank, which might + // have deleted the promise records (if nothing else was + // referencing the promise, like arguments in messages enqueued to + // unresolved promises, or something transient on the + // run-queue). Deleting those promise records might have decreffed + // krefs in the rejection data (although in general 9039 rejects + // those promises with non-slot-bearing DisconnectionObjects). + // + // To avoid duplicating a lot of kernel code inside this upgrade + // handler, we do the simplest possible thing: enqueue a notify to + // the upgraded vat for all these leftover promises. The new vat + // incarnation will ignore it (they don't recognize the vpid), but + // the dispatch.notify() delivery will clear the c-list and decref + // the kpid, and will trigger all the usual GC work. Note that + // these notifies will be delivered before any activity the host + // app might trigger for e.g. a chain upgrade, but they should not + // cause userspace-visible behavior (non-slot-bearing rejection + // data means no other vat will even get a gc-action delivery: + // only the upgraded vat will see anything, and those deliveries + // won't make it past liveslots). + + let count = 0; + for (const [kpid, vatID] of buggyKPIDs) { + // account for the reference to this kpid in upgradeEvents + incrementReferenceCount(getRequired, kvStore, kpid, `enq|notify`); + upgradeEvents.push({ type: 'notify', vatID, kpid }); + count += 1; + } + + console.log(` - #9039 remediation complete, ${count} notifies to inject`); + modified = true; + version = 3; + } + + if (upgradeEvents.length) { + assert(modified); + // stash until host calls controller.injectQueuedUpgradeEvents() + const oldEvents = JSON.parse(kvStore.get('upgradeEvents') || '[]'); + const events = [...oldEvents, ...upgradeEvents]; + kvStore.set('upgradeEvents', JSON.stringify(events)); + } + if (modified) { kvStore.set('version', `${version}`); } - return modified; + return harden({ modified }); }; harden(upgradeSwingset); diff --git a/packages/SwingSet/src/kernel/kernel.js b/packages/SwingSet/src/kernel/kernel.js index b6e11dbd714..5b21dbe0894 100644 --- a/packages/SwingSet/src/kernel/kernel.js +++ b/packages/SwingSet/src/kernel/kernel.js @@ -215,6 +215,10 @@ export default function buildKernel( return deviceID; } + function injectQueuedUpgradeEvents() { + kernelKeeper.injectQueuedUpgradeEvents(); + } + function addImport(forVatID, what) { if (!started) { throw Error('must do kernel.start() before addImport()'); @@ -287,15 +291,16 @@ export default function buildKernel( const vatKeeper = kernelKeeper.provideVatKeeper(vatID); critical = vatKeeper.getOptions().critical; - // Reject all promises decided by the vat, making sure to capture the list - // of kpids before that data is deleted. - const deadPromises = [...kernelKeeper.enumeratePromisesByDecider(vatID)]; - // remove vatID from the list of live vats, and mark for deletion + // remove vatID from the list of live vats, and mark for + // deletion (which will happen later, in vat-cleanup events) kernelKeeper.deleteVatID(vatID); kernelKeeper.markVatAsTerminated(vatID); deferred.push(kernelKeeper.removeVatFromSwingStoreExports(vatID)); - for (const kpid of deadPromises) { - resolveToError(kpid, makeError('vat terminated'), vatID); + + // Reject all promises decided by the vat + const errdata = makeError('vat terminated'); + for (const [kpid, _p] of kernelKeeper.enumeratePromisesByDecider(vatID)) { + resolveToError(kpid, errdata, vatID); } } if (critical) { @@ -597,7 +602,9 @@ export default function buildKernel( const p = kernelKeeper.getKernelPromise(kpid); kernelKeeper.incStat('dispatchNotify'); const vatKeeper = kernelKeeper.provideVatKeeper(vatID); - p.state !== 'unresolved' || Fail`spurious notification ${kpid}`; + if (p.state === 'unresolved') { + throw Fail`spurious notification ${kpid}`; + } /** @type { KernelDeliveryOneNotify[] } */ const resolutions = []; if (!vatKeeper.hasCListEntry(kpid)) { @@ -612,7 +619,9 @@ export default function buildKernel( return NO_DELIVERY_CRANK_RESULTS; } for (const toResolve of targets) { - const { state, data } = kernelKeeper.getKernelPromise(toResolve); + const tp = kernelKeeper.getKernelPromise(toResolve); + assert(tp.state !== 'unresolved'); + const { state, data } = tp; resolutions.push([toResolve, { state, data }]); } /** @type { KernelDeliveryNotify } */ @@ -995,9 +1004,30 @@ export default function buildKernel( return results; } - // reject all promises for which the vat was decider - for (const kpid of kernelKeeper.enumeratePromisesByDecider(vatID)) { - resolveToError(kpid, disconnectionCapData, vatID); + // We are homesick for a future in which most promises are + // durable, and vats do not need to subscribe to their own + // promises to make promise-watchers work. In that world, vats + // somehow mark the non-durable promises, which we must + // reject/disconnect on their behalf during upgrade. + // + // To handle the present reality, without durable promises, we + // pretend that all promises are so marked. + + // reject all ephemeral promises for which the vat was decider + for (const [kpid, p] of kernelKeeper.enumeratePromisesByDecider(vatID)) { + const isEphemeral = true; // future vats will mark these explicitly + const selfSubscribed = + p.state === 'unresolved' && p.subscribers.includes(vatID); + if (isEphemeral) { + resolveToError(kpid, disconnectionCapData, vatID); + if (!selfSubscribed) { + // If the vat was subscribed to its own promise, the + // resolveToError will enqueue a dispatch.notify, whose delivery + // will delete the c-list entry. If it is *not* subscribed, we + // should delete the c-list entry now, because nobody else will. + vatKeeper.deleteCListEntriesForKernelSlots([kpid]); + } + } } // simulate an abandonExports syscall from the vat, @@ -1186,6 +1216,7 @@ export default function buildKernel( } } default: + // @ts-expect-error throw Fail`unknown promise resolution '${kp.state}'`; } } @@ -2081,6 +2112,7 @@ export default function buildKernel( return p.data; } default: { + // @ts-expect-error throw Fail`invalid state for ${kpid}: ${p.state}`; } } @@ -2179,6 +2211,7 @@ export default function buildKernel( pinObject, vatNameToID, deviceNameToID, + injectQueuedUpgradeEvents, queueToKref, kpRegisterInterest, kpStatus, diff --git a/packages/SwingSet/src/kernel/state/kernelKeeper.js b/packages/SwingSet/src/kernel/state/kernelKeeper.js index 1d456160bf8..aab0d1e66b5 100644 --- a/packages/SwingSet/src/kernel/state/kernelKeeper.js +++ b/packages/SwingSet/src/kernel/state/kernelKeeper.js @@ -45,14 +45,16 @@ const enableKernelGC = true; * @typedef { import('../../types-external.js').VatKeeper } VatKeeper * @typedef { import('../../types-internal.js').InternalKernelOptions } InternalKernelOptions * @typedef { import('../../types-internal.js').ReapDirtThreshold } ReapDirtThreshold + * @import {PromiseRecord} from '../../types-internal.js'; * @import {CleanupBudget, CleanupWork, PolicyOutputCleanupBudget} from '../../types-external.js'; * @import {RunQueueEventCleanupTerminatedVat} from '../../types-internal.js'; + * @import {SwingStoreKernelStorage} from '@agoric/swing-store'; */ export { DEFAULT_REAP_DIRT_THRESHOLD_KEY }; // most recent DB schema version -export const CURRENT_SCHEMA_VERSION = 2; +export const CURRENT_SCHEMA_VERSION = 3; // Kernel state lives in a key-value store supporting key retrieval by // lexicographic range. All keys and values are strings. @@ -71,9 +73,9 @@ export const CURRENT_SCHEMA_VERSION = 2; // only modified by a call to upgradeSwingset(). See below for // deltas/upgrades from one version to the next. // -// The current ("v2") schema keys/values are: +// The current ("v3") schema keys/values are: // -// version = '2' +// version = '3' // vat.names = JSON([names..]) // vat.dynamicIDs = JSON([vatIDs..]) // vat.name.$NAME = $vatID = v$NN @@ -141,6 +143,7 @@ export const CURRENT_SCHEMA_VERSION = 2; // gcActions = JSON(gcActions) // reapQueue = JSON([vatIDs...]) // pinnedObjects = ko$NN[,ko$NN..] +// upgradeEvents = JSON([events..]) // ko.nextID = $NN // ko$NN.owner = $vatID @@ -177,6 +180,11 @@ export const CURRENT_SCHEMA_VERSION = 2; // v2: // * change `version` to `'2'` // * add `vats.terminated` with `[]` as initial value +// v3: +// * change `version` to `'3'` +// * perform remediation for bug #9039 +// (after v3, does not get its own version) +// * `upgradeEvents` recognized, but omitted if empty /** @type {(s: string) => string[]} s */ export function commaSplit(s) { @@ -212,6 +220,77 @@ export const getAllDynamicVats = getRequired => { return JSON.parse(getRequired('vat.dynamicIDs')); }; +const getObjectReferenceCount = (kvStore, kref) => { + const data = kvStore.get(`${kref}.refCount`); + if (!data) { + return { reachable: 0, recognizable: 0 }; + } + const [reachable, recognizable] = commaSplit(data).map(Number); + reachable <= recognizable || + Fail`refmismatch(get) ${kref} ${reachable},${recognizable}`; + return { reachable, recognizable }; +}; + +const setObjectReferenceCount = (kvStore, kref, counts) => { + const { reachable, recognizable } = counts; + assert.typeof(reachable, 'number'); + assert.typeof(recognizable, 'number'); + (reachable >= 0 && recognizable >= 0) || + Fail`${kref} underflow ${reachable},${recognizable}`; + reachable <= recognizable || + Fail`refmismatch(set) ${kref} ${reachable},${recognizable}`; + kvStore.set(`${kref}.refCount`, `${reachable},${recognizable}`); +}; + +/** + * Increment the reference count associated with some kernel object. + * + * We track references to promises and objects, but not devices. Promises + * have only a "reachable" count, whereas objects track both "reachable" + * and "recognizable" counts. + * + * @param { (key: string) => string} getRequired + * @param { import('@agoric/swing-store').KVStore } kvStore + * @param {string} kref The kernel slot whose refcount is to be incremented. + * @param {string?} tag Debugging note with rough source of the reference. + * @param {{ isExport?: boolean, onlyRecognizable?: boolean }} options + * 'isExport' means the reference comes from a clist export, which counts + * for promises but not objects. 'onlyRecognizable' means the reference + * provides only recognition, not reachability + */ +export const incrementReferenceCount = ( + getRequired, + kvStore, + kref, + tag, + options = {}, +) => { + const { isExport = false, onlyRecognizable = false } = options; + kref || Fail`incrementRefCount called with empty kref, tag=${tag}`; + const { type } = parseKernelSlot(kref); + if (type === 'promise') { + const refCount = Number(getRequired(`${kref}.refCount`)) + 1; + // kdebug(`++ ${kref} ${tag} ${refCount}`); + kvStore.set(`${kref}.refCount`, `${refCount}`); + } + if (type === 'object' && !isExport) { + let { reachable, recognizable } = getObjectReferenceCount(kvStore, kref); + if (!onlyRecognizable) { + reachable += 1; + } + recognizable += 1; + // kdebug(`++ ${kref} ${tag} ${reachable},${recognizable}`); + setObjectReferenceCount(kvStore, kref, { reachable, recognizable }); + } +}; + +export function* readQueue(queue, getRequired) { + const [head, tail] = JSON.parse(getRequired(`${queue}`)); + for (let i = head; i < tail; i += 1) { + yield JSON.parse(getRequired(`${queue}.${i}`)); + } +} + // we use different starting index values for the various vNN/koNN/kdNN/kpNN // slots, to reduce confusing overlap when looking at debug messages (e.g. // seeing both kp1 and ko1, which are completely unrelated despite having the @@ -389,14 +468,7 @@ export default function makeKernelKeeper( return tail - head; } - function dumpQueue(queue) { - const [head, tail] = JSON.parse(getRequired(`${queue}`)); - const result = []; - for (let i = head; i < tail; i += 1) { - result.push(JSON.parse(getRequired(`${queue}.${i}`))); - } - return result; - } + const dumpQueue = queue => [...readQueue(queue, getRequired)]; /** * @param {InternalKernelOptions} kernelOptions @@ -620,26 +692,9 @@ export default function makeKernelKeeper( return parseReachableAndVatSlot(kvStore.get(kernelKey)); } - function getObjectRefCount(kernelSlot) { - const data = kvStore.get(`${kernelSlot}.refCount`); - if (!data) { - return { reachable: 0, recognizable: 0 }; - } - const [reachable, recognizable] = commaSplit(data).map(Number); - reachable <= recognizable || - Fail`refmismatch(get) ${kernelSlot} ${reachable},${recognizable}`; - return { reachable, recognizable }; - } - - function setObjectRefCount(kernelSlot, { reachable, recognizable }) { - assert.typeof(reachable, 'number'); - assert.typeof(recognizable, 'number'); - (reachable >= 0 && recognizable >= 0) || - Fail`${kernelSlot} underflow ${reachable},${recognizable}`; - reachable <= recognizable || - Fail`refmismatch(set) ${kernelSlot} ${reachable},${recognizable}`; - kvStore.set(`${kernelSlot}.refCount`, `${reachable},${recognizable}`); - } + const getObjectRefCount = kref => getObjectReferenceCount(kvStore, kref); + const setObjectRefCount = (kref, counts) => + setObjectReferenceCount(kvStore, kref, counts); /** * Iterate over non-durable objects exported by a vat. @@ -791,45 +846,41 @@ export default function makeKernelKeeper( return kpid; } + /** + * @param {string} kernelSlot + * @returns {PromiseRecord} + */ function getKernelPromise(kernelSlot) { insistKernelType('promise', kernelSlot); - const p = { state: getRequired(`${kernelSlot}.state`) }; - switch (p.state) { - case undefined: { - throw Fail`unknown kernelPromise '${kernelSlot}'`; - } + const state = getRequired(`${kernelSlot}.state`); + const refCount = Number(kvStore.get(`${kernelSlot}.refCount`)); + switch (state) { case 'unresolved': { - p.refCount = Number(kvStore.get(`${kernelSlot}.refCount`)); - p.decider = kvStore.get(`${kernelSlot}.decider`); - if (p.decider === '') { - p.decider = undefined; - } - p.policy = kvStore.get(`${kernelSlot}.policy`) || 'ignore'; - // @ts-expect-error get() may fail - p.subscribers = commaSplit(kvStore.get(`${kernelSlot}.subscribers`)); - p.queue = Array.from( + const decider = kvStore.get(`${kernelSlot}.decider`) || undefined; + const policy = kvStore.get(`${kernelSlot}.policy`) || 'ignore'; + const subscribers = commaSplit( + kvStore.get(`${kernelSlot}.subscribers`) || '', + ); + const queue = Array.from( getPrefixedValues(kvStore, `${kernelSlot}.queue.`), ).map(s => JSON.parse(s)); - break; + return harden({ state, refCount, decider, policy, subscribers, queue }); } case 'fulfilled': case 'rejected': { - p.refCount = Number(kvStore.get(`${kernelSlot}.refCount`)); - p.data = { - body: kvStore.get(`${kernelSlot}.data.body`), - // @ts-expect-error get() may fail - slots: commaSplit(kvStore.get(`${kernelSlot}.data.slots`)), + const data = { + body: getRequired(`${kernelSlot}.data.body`), + slots: commaSplit(getRequired(`${kernelSlot}.data.slots`)), }; - for (const s of p.data.slots) { + for (const s of data.slots) { parseKernelSlot(s); } - break; + return harden({ state, refCount, data }); } default: { - throw Fail`unknown state for ${kernelSlot}: ${p.state}`; + throw Fail`unknown state for ${kernelSlot}: ${state}`; } } - return harden(p); } function getResolveablePromise(kpid, expectedDecider) { @@ -838,7 +889,9 @@ export default function makeKernelKeeper( insistVatID(expectedDecider); } const p = getKernelPromise(kpid); - p.state === 'unresolved' || Fail`${kpid} was already resolved`; + if (p.state !== 'unresolved') { + throw Fail`${kpid} was already resolved`; + } if (expectedDecider) { p.decider === expectedDecider || Fail`${kpid} is decided by ${p.decider}, not ${expectedDecider}`; @@ -897,6 +950,7 @@ export default function makeKernelKeeper( // up the resolution *now* and set the correct target early. Doing that // might make it easier to remove the Promise Table entry earlier. const p = getKernelPromise(kernelSlot); + assert.equal(p.state, 'unresolved'); for (const msg of p.queue) { const entry = harden({ type: 'send', target: kernelSlot, msg }); enqueue('acceptanceQueue', entry); @@ -1142,18 +1196,22 @@ export default function makeKernelKeeper( function setDecider(kpid, decider) { insistVatID(decider); const p = getKernelPromise(kpid); - p.state === 'unresolved' || Fail`${kpid} was already resolved`; - !p.decider || Fail`${kpid} has decider ${p.decider}, not empty`; + assert.equal(p.state, 'unresolved', `${kpid} was already resolved`); + assert(!p.decider, `${kpid} has decider ${p.decider}, not empty`); kvStore.set(`${kpid}.decider`, decider); } function clearDecider(kpid) { const p = getKernelPromise(kpid); - p.state === 'unresolved' || Fail`${kpid} was already resolved`; - p.decider || Fail`${kpid} does not have a decider`; + assert.equal(p.state, 'unresolved', `${kpid} was already resolved`); + assert(p.decider, `${kpid} does not have a decider`); kvStore.set(`${kpid}.decider`, ''); } + /** + * @param {string} vatID + * @returns {IterableIterator<[kpid: string, p: PromiseRecord]>} + */ function* enumeratePromisesByDecider(vatID) { insistVatID(vatID); const promisePrefix = `${vatID}.c.p`; @@ -1167,10 +1225,10 @@ export default function makeKernelKeeper( // whether the vat is the decider or not. If it is, we add the promise // to the list of promises that must be rejected because the dead vat // will never be able to act upon them. - const kpid = kvStore.get(k); + const kpid = getRequired(k); const p = getKernelPromise(kpid); if (p.state === 'unresolved' && p.decider === vatID) { - yield kpid; + yield [kpid, p]; } } } @@ -1180,6 +1238,7 @@ export default function makeKernelKeeper( insistKernelType('promise', kernelSlot); insistVatID(vatID); const p = getKernelPromise(kernelSlot); + assert.equal(p.state, 'unresolved'); const s = new Set(p.subscribers); s.add(vatID); const v = Array.from(s).sort().join(','); @@ -1210,6 +1269,27 @@ export default function makeKernelKeeper( return dequeue('acceptanceQueue'); } + function injectQueuedUpgradeEvents() { + // refcounts: Any krefs in `upgradeEvents` must have a refcount to + // represent the list's hold on those objects. When + // upgradeSwingset() creates these events, it must also + // incref(kref), otherwise we run the risk of dropping the kref by + // the time injectQueuedUpgradeEvents() is called. We're nominally + // removing each event from upgradeEvents (decref), then pushing + // it onto the run-queue (incref), but since those two cancel each + // other out, we don't actually need to modify any reference + // counts from within this function. Note that + // addToAcceptanceQueue does not increment refcounts, just kernel + // queue-length stats. + + const events = JSON.parse(kvStore.get('upgradeEvents') || '[]'); + kvStore.delete('upgradeEvents'); + for (const e of events) { + assert(e.type, `not an event`); + addToAcceptanceQueue(e); + } + } + function allocateMeter(remaining, threshold) { if (remaining !== 'unlimited') { assert.typeof(remaining, 'bigint'); @@ -1417,40 +1497,8 @@ export default function makeKernelKeeper( maybeFreeKrefs.add(kref); } - /** - * Increment the reference count associated with some kernel object. - * - * We track references to promises and objects, but not devices. Promises - * have only a "reachable" count, whereas objects track both "reachable" - * and "recognizable" counts. - * - * @param {unknown} kernelSlot The kernel slot whose refcount is to be incremented. - * @param {string?} tag Debugging note with rough source of the reference. - * @param {{ isExport?: boolean, onlyRecognizable?: boolean }} options - * 'isExport' means the reference comes from a clist export, which counts - * for promises but not objects. 'onlyRecognizable' means the reference - * provides only recognition, not reachability - */ - function incrementRefCount(kernelSlot, tag, options = {}) { - const { isExport = false, onlyRecognizable = false } = options; - kernelSlot || - Fail`incrementRefCount called with empty kernelSlot, tag=${tag}`; - const { type } = parseKernelSlot(kernelSlot); - if (type === 'promise') { - const refCount = Nat(BigInt(getRequired(`${kernelSlot}.refCount`))) + 1n; - // kdebug(`++ ${kernelSlot} ${tag} ${refCount}`); - kvStore.set(`${kernelSlot}.refCount`, `${refCount}`); - } - if (type === 'object' && !isExport) { - let { reachable, recognizable } = getObjectRefCount(kernelSlot); - if (!onlyRecognizable) { - reachable += 1; - } - recognizable += 1; - // kdebug(`++ ${kernelSlot} ${tag} ${reachable},${recognizable}`); - setObjectRefCount(kernelSlot, { reachable, recognizable }); - } - } + const incrementRefCount = (kref, tag, options = {}) => + incrementReferenceCount(getRequired, kvStore, kref, tag, options); /** * Decrement the reference count associated with some kernel object. @@ -1542,13 +1590,15 @@ export default function makeKernelKeeper( const kp = getKernelPromise(kpid); if (kp.refCount === 0) { let idx = 0; - // TODO (#9889) don't assume promise is settled - for (const slot of kp.data.slots) { - // Note: the following decrement can result in an addition to the - // maybeFreeKrefs set, which we are in the midst of iterating. - // TC39 went to a lot of trouble to ensure that this is kosher. - decrementRefCount(slot, `gc|${kpid}|s${idx}`); - idx += 1; + if (kp.state === 'fulfilled' || kp.state === 'rejected') { + // #9889 don't assume promise is settled + for (const slot of kp.data.slots) { + // Note: the following decrement can result in an addition to the + // maybeFreeKrefs set, which we are in the midst of iterating. + // TC39 went to a lot of trouble to ensure that this is kosher. + decrementRefCount(slot, `gc|${kpid}|s${idx}`); + idx += 1; + } } deleteKernelPromise(kpid); } @@ -1939,6 +1989,8 @@ export default function makeKernelKeeper( getAcceptanceQueueLength, getNextAcceptanceQueueMsg, + injectQueuedUpgradeEvents, + allocateMeter, addMeterRemaining, setMeterThreshold, diff --git a/packages/SwingSet/src/kernel/vatTranslator.js b/packages/SwingSet/src/kernel/vatTranslator.js index d781a41cf38..10a7f9559ae 100644 --- a/packages/SwingSet/src/kernel/vatTranslator.js +++ b/packages/SwingSet/src/kernel/vatTranslator.js @@ -50,6 +50,7 @@ function makeTranslateKernelDeliveryToVatDelivery(vatID, kernelKeeper) { parseVatSlot(targetSlot).allocatedByVat || Fail`deliver() to wrong vat`; } else if (type === 'promise') { const p = kernelKeeper.getKernelPromise(target); + assert(p.state === 'unresolved'); p.decider === vatID || Fail`wrong decider`; } const inputSlots = msg.methargs.slots.map(slot => @@ -59,7 +60,9 @@ function makeTranslateKernelDeliveryToVatDelivery(vatID, kernelKeeper) { if (msg.result) { insistKernelType('promise', msg.result); const p = kernelKeeper.getKernelPromise(msg.result); - p.state === 'unresolved' || Fail`result ${msg.result} already resolved`; + if (p.state !== 'unresolved') { + throw Fail`result ${msg.result} already resolved`; + } !p.decider || Fail`result ${msg.result} already has decider ${p.decider}`; resultSlot = vatKeeper.mapKernelSlotToVatSlot(msg.result); insistVatType('promise', resultSlot); @@ -318,8 +321,9 @@ function makeTranslateVatSyscallToKernelSyscall(vatID, kernelKeeper) { // In the case of non-pipelining vats these checks are redundant since // we're guaranteed to have a promise newly allocated by the vat. const p = kernelKeeper.getKernelPromise(result); - p.state === 'unresolved' || - Fail`send() result ${result} is already resolved`; + if (p.state !== 'unresolved') { + throw Fail`send() result ${result} is already resolved`; + } p.decider === vatID || Fail`send() result ${result} is decided by ${p.decider} not ${vatID}`; kernelKeeper.clearDecider(result); diff --git a/packages/SwingSet/src/types-internal.js b/packages/SwingSet/src/types-internal.js index 1ef68a5735f..7a4b2ef1604 100644 --- a/packages/SwingSet/src/types-internal.js +++ b/packages/SwingSet/src/types-internal.js @@ -92,6 +92,17 @@ export {}; * @property {number} [computrons] */ +/** + * @typedef {{ state: 'unresolved', refCount: number, + * decider: string | undefined, policy: string, + * subscribers: string[], queue: string[], + * }} UnresolvedPromiseRecord + * @typedef {{ state: 'fulfilled' | 'rejected', refCount: number, + * data: SwingSetCapData, + * }} SettledPromiseRecord + * @typedef {UnresolvedPromiseRecord | SettledPromiseRecord} PromiseRecord + */ + /** * @typedef {{ * enablePipelining: boolean, diff --git a/packages/SwingSet/test/kernel.test.js b/packages/SwingSet/test/kernel.test.js index f18a0720ff3..ef17e333a34 100644 --- a/packages/SwingSet/test/kernel.test.js +++ b/packages/SwingSet/test/kernel.test.js @@ -1817,3 +1817,46 @@ test('reap gc-krefs 12', async t => { test('reap gc-krefs overrideNever', async t => { await reapGCKrefsTest(t, 12, true); }); + +test('injectQueuedUpgradeEvents', async t => { + const endowments = makeKernelEndowments(); + const { kernelStorage } = endowments; + const { kvStore } = kernelStorage; + await initializeKernel({}, kernelStorage); + const kernel = buildKernel(endowments, {}, {}); + await kernel.start(); + // TODO: extract `queueLength`/`dumpQueue` from kernelKeeper.js? + { + const [start, end] = JSON.parse(kvStore.get('acceptanceQueue')); + t.deepEqual([start, end], [1, 1]); + } + + // These events would fail if they actually got processed: the vatID + // and all the krefs are fake, the methargs are not valid capdata, + // and we haven't updated refcounts. But all we care about is that + // they make it onto the acceptance queue. + const vatID = 'v1'; + const e1 = harden({ type: 'notify', vatID, kpid: 'kp25' }); + // kernelKeeper.incrementRefCount(kpid, `enq|notify`); + const target = 'ko11'; + const methargs = ''; + const msg = harden({ methargs, result: 'kp33' }); + const e2 = harden({ type: 'send', target, msg }); + kvStore.set('upgradeEvents', JSON.stringify([e1, e2])); + + kernel.injectQueuedUpgradeEvents([e1, e2]); + + { + const [start, end] = JSON.parse(kvStore.get('acceptanceQueue')); + t.deepEqual([start, end], [1, 3]); + t.deepEqual(JSON.parse(kvStore.get('acceptanceQueue.1')), e1); + t.deepEqual(JSON.parse(kvStore.get('acceptanceQueue.2')), e2); + } + + // It'd be nice to also check that the stats were incremented: + // stats.acceptanceQueueLength shoule be 2, acceptanceQueueLengthUp + // should be 2, and acceptanceQueueLengthMax should be 2. But the + // stats are held in RAM until a crank is executed, and we're not + // doing that here. And the kernel hides the kernelKeeper so we + // can't call getStats() to check. +}); diff --git a/packages/SwingSet/test/snapshots/state.test.js.md b/packages/SwingSet/test/snapshots/state.test.js.md index 4c02a66077d..674e2a3c811 100644 --- a/packages/SwingSet/test/snapshots/state.test.js.md +++ b/packages/SwingSet/test/snapshots/state.test.js.md @@ -8,8 +8,8 @@ Generated by [AVA](https://avajs.dev). > initial state - '7b16bffd29f6a2d11bae7b536ef4c230af8cadc29284928b6cc2f7338507a987' + 'af35907384e9d63dd9fc4d4df0440005c0ee81ef88f86089a0e0a280fe3793af' > expected activityhash - '7dbf5a49d4e2b999c431730fcd4927c01c713eaa54fe273626e4201853e38d3b' + '040e27413c25f3ce668d9778add3b3d39547358ded553c0b9fba898004968d1b' diff --git a/packages/SwingSet/test/snapshots/state.test.js.snap b/packages/SwingSet/test/snapshots/state.test.js.snap index 0efcf0fac96..a4a79f56520 100644 Binary files a/packages/SwingSet/test/snapshots/state.test.js.snap and b/packages/SwingSet/test/snapshots/state.test.js.snap differ diff --git a/packages/SwingSet/test/state.test.js b/packages/SwingSet/test/state.test.js index c60a01aa79c..16450ab7b17 100644 --- a/packages/SwingSet/test/state.test.js +++ b/packages/SwingSet/test/state.test.js @@ -183,7 +183,7 @@ test('kernel state', async t => { k.emitCrankHashes(); checkState(t, store.dump, [ - ['version', '2'], + ['version', '3'], ['crankNumber', '0'], ['gcActions', '[]'], ['runQueue', '[1,1]'], @@ -223,7 +223,7 @@ test('kernelKeeper vat names', async t => { k.emitCrankHashes(); checkState(t, store.dump, [ - ['version', '2'], + ['version', '3'], ['crankNumber', '0'], ['gcActions', '[]'], ['runQueue', '[1,1]'], @@ -279,7 +279,7 @@ test('kernelKeeper device names', async t => { k.emitCrankHashes(); checkState(t, store.dump, [ - ['version', '2'], + ['version', '3'], ['crankNumber', '0'], ['gcActions', '[]'], ['runQueue', '[1,1]'], @@ -462,7 +462,7 @@ test('kernelKeeper promises', async t => { k.emitCrankHashes(); checkState(t, store.dump, [ - ['version', '2'], + ['version', '3'], ['crankNumber', '0'], ['device.nextID', '7'], ['vat.nextID', '1'], @@ -1078,7 +1078,7 @@ test('dirt upgrade', async t => { // * v3.reapCountdown: 'never' // * v3.reapInterval: 'never' - t.is(k.kvStore.get('version'), '2'); + t.is(k.kvStore.get('version'), '3'); k.kvStore.delete(`kernel.defaultReapDirtThreshold`); k.kvStore.set(`kernel.defaultReapInterval`, '1000'); @@ -1109,12 +1109,15 @@ test('dirt upgrade', async t => { // it requires a manual upgrade let k2; + let ks2; { const serialized = store.serialize(); const { kernelStorage } = initSwingStore(null, { serialized }); - upgradeSwingset(kernelStorage); + const { modified } = upgradeSwingset(kernelStorage); + t.true(modified); k2 = makeKernelKeeper(kernelStorage, CURRENT_SCHEMA_VERSION); // works this time k2.loadStats(); + ks2 = kernelStorage; } t.true(k2.kvStore.has(`kernel.defaultReapDirtThreshold`)); @@ -1157,6 +1160,12 @@ test('dirt upgrade', async t => { t.deepEqual(JSON.parse(k2.kvStore.get(`${v3}.options`)).reapDirtThreshold, { never: true, }); + + { + // upgrade is idempotent + const { modified } = upgradeSwingset(ks2); + t.false(modified); + } }); test('v2 upgrade', async t => { @@ -1168,7 +1177,7 @@ test('v2 upgrade', async t => { k.saveStats(); // roll back to v1 - t.is(k.kvStore.get('version'), '2'); + t.is(k.kvStore.get('version'), '3'); k.kvStore.delete(`vats.terminated`); k.kvStore.set('version', '1'); @@ -1177,15 +1186,24 @@ test('v2 upgrade', async t => { // it requires a manual upgrade let k2; + let ks2; { const serialized = store.serialize(); const { kernelStorage } = initSwingStore(null, { serialized }); - upgradeSwingset(kernelStorage); + const { modified } = upgradeSwingset(kernelStorage); + t.true(modified); k2 = makeKernelKeeper(kernelStorage, CURRENT_SCHEMA_VERSION); // works this time k2.loadStats(); + ks2 = kernelStorage; } t.true(k2.kvStore.has(`vats.terminated`)); t.deepEqual(JSON.parse(k2.kvStore.get(`vats.terminated`)), []); - t.is(k2.kvStore.get(`version`), '2'); + t.is(k2.kvStore.get(`version`), '3'); + + { + // upgrade is idempotent + const { modified } = upgradeSwingset(ks2); + t.false(modified); + } }); diff --git a/packages/SwingSet/test/transcript-light.test.js b/packages/SwingSet/test/transcript-light.test.js index 9049eb57845..e911a4e3451 100644 --- a/packages/SwingSet/test/transcript-light.test.js +++ b/packages/SwingSet/test/transcript-light.test.js @@ -17,7 +17,7 @@ test('transcript-light load', async t => { t.teardown(c.shutdown); const serialized0 = debug.serialize(); const kvstate0 = debug.dump().kvEntries; - t.is(kvstate0.version, '2'); + t.is(kvstate0.version, '3'); t.is(kvstate0.runQueue, '[1,1]'); t.not(kvstate0.acceptanceQueue, '[]'); diff --git a/packages/SwingSet/test/upgrade-swingset.test.js b/packages/SwingSet/test/upgrade-swingset.test.js index a18b2699dd8..ca88649d3bb 100644 --- a/packages/SwingSet/test/upgrade-swingset.test.js +++ b/packages/SwingSet/test/upgrade-swingset.test.js @@ -1,9 +1,11 @@ -/* eslint-disable no-underscore-dangle */ // @ts-nocheck -import { initSwingStore } from '@agoric/swing-store'; +// eslint-disable-next-line import/order import { test } from '../tools/prepare-test-env-ava.js'; +import { initSwingStore } from '@agoric/swing-store'; +import { kser } from '@agoric/kmarshal'; + import { initializeSwingset, makeSwingsetController, @@ -28,7 +30,7 @@ test('kernel refuses to run with out-of-date DB - v0', async t => { // kernelkeeper v0 schema, just deleting the version key and adding // 'initialized' - t.is(kvStore.get('version'), '2'); + t.is(kvStore.get('version'), '3'); kvStore.delete(`version`); kvStore.set('initialized', 'true'); await commit(); @@ -51,7 +53,7 @@ test('kernel refuses to run with out-of-date DB - v1', async t => { // kernelkeeper v1 schema, by reducing the version key and removing // vats.terminated - t.is(kvStore.get('version'), '2'); + t.is(kvStore.get('version'), '3'); kvStore.set(`version`, '1'); kvStore.delete('vats.terminated'); await commit(); @@ -62,6 +64,28 @@ test('kernel refuses to run with out-of-date DB - v1', async t => { }); }); +test('kernel refuses to run with out-of-date DB - v2', async t => { + const { hostStorage, kernelStorage } = initSwingStore(); + const { commit } = hostStorage; + const { kvStore } = kernelStorage; + const config = {}; + await initializeSwingset(config, [], kernelStorage, t.context.data); + await commit(); + + // now doctor the initial state to make it look like the + // kernelkeeper v2 schema, by reducing the version key and removing + // vats.terminated + + t.is(kvStore.get('version'), '3'); + kvStore.set(`version`, '2'); + await commit(); + + // Now build a controller around this modified state, which should fail. + await t.throwsAsync(() => makeSwingsetController(kernelStorage), { + message: /kernel DB is too old/, + }); +}); + test('upgrade kernel state', async t => { const { hostStorage, kernelStorage } = initSwingStore(); const { commit } = hostStorage; @@ -96,7 +120,7 @@ test('upgrade kernel state', async t => { t.true(kvStore.has('kernel.defaultReapDirtThreshold')); - t.is(kvStore.get('version'), '2'); + t.is(kvStore.get('version'), '3'); kvStore.delete('version'); // i.e. revert to v0 kvStore.set('initialized', 'true'); kvStore.delete('vats.terminated'); @@ -137,7 +161,8 @@ test('upgrade kernel state', async t => { upgradeSwingset(kernelStorage); // now we should be good to go - const _controller = await makeSwingsetController(kernelStorage); + const controller = await makeSwingsetController(kernelStorage); + controller.injectQueuedUpgradeEvents(); t.true(kvStore.has('kernel.defaultReapDirtThreshold')); // the kernel-wide threshold gets a .gcKrefs (to meet our upcoming @@ -186,7 +211,7 @@ test('upgrade non-reaping kernel state', async t => { t.true(kvStore.has('kernel.defaultReapDirtThreshold')); - t.is(kvStore.get('version'), '2'); + t.is(kvStore.get('version'), '3'); kvStore.delete('version'); // i.e. revert to v0 kvStore.set('initialized', 'true'); kvStore.delete('vats.terminated'); @@ -220,7 +245,8 @@ test('upgrade non-reaping kernel state', async t => { upgradeSwingset(kernelStorage); // now we should be good to go - const _controller = await makeSwingsetController(kernelStorage); + const controller = await makeSwingsetController(kernelStorage); + controller.injectQueuedUpgradeEvents(); t.true(kvStore.has('kernel.defaultReapDirtThreshold')); t.deepEqual(JSON.parse(kvStore.get('kernel.defaultReapDirtThreshold')), { @@ -229,3 +255,211 @@ test('upgrade non-reaping kernel state', async t => { gcKrefs: 'never', }); }); + +test('v3 upgrade', async t => { + // exercise the remediation code for bug #9039 + const { hostStorage, kernelStorage, debug } = initSwingStore(); + const { commit } = hostStorage; + const { kvStore } = kernelStorage; + const config = {}; + await initializeSwingset(config, [], kernelStorage, t.context.data); + await commit(); + + // doctor the initial state to inject #9039 problems, then check + // that upgrade applies the expected fixes. We pretend that + // v1-vatAdmin was upgraded and left some promises lying around. + + const vatID = kvStore.get('vat.name.vatAdmin'); + t.truthy(vatID); + + const disconnectionObject = { + name: 'vatUpgraded', + upgradeMessage: 'test upgrade', + incarnationNumber: 0, + }; + const dccd = kser(disconnectionObject); + + t.is(kvStore.get('version'), '3'); + kvStore.set('version', '2'); // revert to v2 + const runQueue = []; + const acceptanceQueue = []; + const nextID = Number(kvStore.get('kp.nextID')); + const p1 = `kp${nextID}`; + const p2 = `kp${nextID + 1}`; + const p3 = `kp${nextID + 2}`; + const p4 = `kp${nextID + 3}`; + const p5 = `kp${nextID + 4}`; + const p6 = `kp${nextID + 5}`; + kvStore.set('kp.nextID', `${nextID + 6}`); + + // first promise "was" known only to the upgraded vat, but not + // self-subscribed, so no notify was sent: remediated + kvStore.set(`${p1}.state`, 'rejected'); + kvStore.set(`${p1}.data.body`, dccd.body); + kvStore.set(`${p1}.data.slots`, ''); + kvStore.set(`${p1}.refCount`, '1'); + kvStore.set(`${vatID}.c.${p1}`, 'R p+90'); + kvStore.set(`${vatID}.c.p+90`, p1); + + // second promise was also only known to upgraded vat, but we + // pretend it was self-subscribed, and the notify is still sitting + // in the run-queue: ignored + kvStore.set(`${p2}.state`, 'rejected'); + kvStore.set(`${p2}.data.body`, dccd.body); + kvStore.set(`${p2}.data.slots`, ''); + kvStore.set(`${p2}.refCount`, '2'); // c-list, runQueue + kvStore.set(`${vatID}.c.${p2}`, 'R p+91'); + kvStore.set(`${vatID}.c.p+91`, p2); + runQueue.push({ type: 'notify', vatID, kpid: p2 }); + + // third promise is only known to upgraded vat, but self-subscribed, + // and the notify is still sitting in the acceptance queue: ignored + kvStore.set(`${p3}.state`, 'rejected'); + kvStore.set(`${p3}.data.body`, dccd.body); + kvStore.set(`${p3}.data.slots`, ''); + kvStore.set(`${p3}.refCount`, '2'); // c-list, acceptanceQueue + kvStore.set(`${vatID}.c.${p3}`, 'R p+92'); + kvStore.set(`${vatID}.c.p+92`, p3); + acceptanceQueue.push({ type: 'notify', vatID, kpid: p3 }); + + // fourth promise has additional references, still remediated + kvStore.set(`${p4}.state`, 'rejected'); + kvStore.set(`${p4}.data.body`, dccd.body); + kvStore.set(`${p4}.data.slots`, ''); + // note: we aren't being specific about *where* the other reference + // is coming from. A plausible source is an argument of a message + // queued to some other unresolved promise. A non-plausible one is + // in the c-list of some other vat (as a settled promise that one + // should have gotten a notify too, assuming they were subscribed, + // and they shouldn't be not subscribed). If the refcounts were + // stored in a DB with more runtime checking, we'd be creating an + // illegal situation here, but it's not. + kvStore.set(`${p4}.refCount`, '2'); // c-list, other + kvStore.set(`${vatID}.c.${p4}`, 'R p+93'); + kvStore.set(`${vatID}.c.p+93`, p4); + + // fifth promise is fulfilled, not rejected, without a notify: + // remediated (even though strictly speaking 9039 is about rejected + // promises) + kvStore.set(`${p5}.state`, 'fulfilled'); + kvStore.set(`${p5}.data.body`, '#{}'); + kvStore.set(`${p5}.data.slots`, ''); + kvStore.set(`${p5}.refCount`, '1'); + kvStore.set(`${vatID}.c.${p5}`, 'R p+95'); + kvStore.set(`${vatID}.c.p+95`, p5); + + // sixth promise is unresolved: ignored + kvStore.set(`${p6}.state`, 'unresolved'); + kvStore.set(`${p6}.subscribers`, ''); + kvStore.set(`${p6}.queue.nextID`, `0`); + kvStore.set(`${p6}.refCount`, `1`); + kvStore.set(`${p6}.decider`, vatID); + kvStore.set(`${vatID}.c.${p6}`, 'R p+96'); + kvStore.set(`${vatID}.c.p+96`, p6); + + // now update queues + + // eslint-disable-next-line prefer-const + let [runHead, runTail] = JSON.parse(kvStore.get('runQueue')); + for (const m of runQueue) { + kvStore.set(`runQueue.${runTail}`, JSON.stringify(m)); + runTail += 1; + } + kvStore.set('runQueue', JSON.stringify([runHead, runTail])); + + // eslint-disable-next-line prefer-const + let [accHead, accTail] = JSON.parse(kvStore.get('acceptanceQueue')); + for (const m of acceptanceQueue) { + kvStore.set(`acceptanceQueue.${accTail}`, JSON.stringify(m)); + accTail += 1; + } + kvStore.set('acceptanceQueue', JSON.stringify([accHead, accTail])); + + const stats = JSON.parse(kvStore.get('kernelStats')); + stats.runQueueLength += runQueue.length; + stats.runQueueLengthUp += runQueue.length; + stats.runQueueLengthMax = runQueue.length; + stats.acceptanceQueueLength += acceptanceQueue.length; + stats.acceptanceQueueLengthUp += acceptanceQueue.length; + stats.acceptanceQueueLengthMax = acceptanceQueue.length; + kvStore.set('kernelStats', JSON.stringify(stats)); + + await commit(); + + const data = { ...debug.dump().kvEntries }; + + // confirm that this state is too old for the kernel to use + await t.throwsAsync(() => makeSwingsetController(kernelStorage), { + message: /kernel DB is too old/, + }); + + // upgrade it + const { modified } = upgradeSwingset(kernelStorage); + t.true(modified); + + // there should be `upgradeEvents` in the kvStore + const expected = [ + { type: 'notify', vatID, kpid: p1 }, + { type: 'notify', vatID, kpid: p4 }, + { type: 'notify', vatID, kpid: p5 }, + ]; + t.deepEqual(JSON.parse(kvStore.get('upgradeEvents')), expected); + + // DB updated, now we should be ready to build the controller + const controller = await makeSwingsetController(kernelStorage); + + // but the events remain until the controller is told to inject them + t.deepEqual(JSON.parse(kvStore.get('upgradeEvents')), expected); + + // and then they're removed + controller.injectQueuedUpgradeEvents(); + t.is(kvStore.get('upgradeEvents'), undefined); + + // check state by mutating our dumped copy and then comparing + // against a new dump + + t.deepEqual({ a: 1, b: 2 }, { b: 2, a: 1 }); + // expect notifies for p1/p4/p5 in acceptance queue + const [head, tail] = JSON.parse(kvStore.get('acceptanceQueue')); + t.is(head, accHead); + t.is(tail, accTail + 3); + data.acceptanceQueue = JSON.stringify([accHead, accTail + 3]); + // note: we aren't JSON-parsing the entries, so this depends upon + // the properties being assigned in this exact order + const np1 = JSON.stringify({ type: 'notify', vatID, kpid: p1 }); + data[`acceptanceQueue.${tail - 3}`] = np1; + const np4 = JSON.stringify({ type: 'notify', vatID, kpid: p4 }); + data[`acceptanceQueue.${tail - 2}`] = np4; + const np5 = JSON.stringify({ type: 'notify', vatID, kpid: p5 }); + data[`acceptanceQueue.${tail - 1}`] = np5; + + // note: the in-RAM copy of kernelStats will have the elevated + // acceptance-queue counters, but these are not written to the + // kvStore until a crank is executed, so the data we're comparing + // won't see them + // + // stats = JSON.parse(data.kernelStats); + // stats.acceptanceQueueLength += 3; + // stats.acceptanceQueueLengthUp += 3; + // stats.acceptanceQueueLengthMax = stats.acceptanceQueueLength; + // data.kernelStats = JSON.stringify(stats); + + // the refcounts should now be one larger, because of the queued + // notifies + data[`${p1}.refCount`] = '2'; + data[`${p2}.refCount`] = '2'; + data[`${p3}.refCount`] = '2'; + data[`${p4}.refCount`] = '3'; + data[`${p5}.refCount`] = '2'; + data[`${p6}.refCount`] = '1'; + + // the version is bumped, indicating we don't need to perform this + // remediation again (because the bug is fixed and we won't be + // creating similar corruption in the future) + data.version = '3'; + + // no other state changes are expected + + const newData = { ...debug.dump().kvEntries }; + t.deepEqual(data, newData); +}); diff --git a/packages/SwingSet/test/upgrade/bootstrap-scripted-upgrade.js b/packages/SwingSet/test/upgrade/bootstrap-scripted-upgrade.js index c93cfa6b568..c6bbde12178 100644 --- a/packages/SwingSet/test/upgrade/bootstrap-scripted-upgrade.js +++ b/packages/SwingSet/test/upgrade/bootstrap-scripted-upgrade.js @@ -78,8 +78,16 @@ export const buildRootObject = () => { p1.catch(() => 'hush'); const p2 = E(ulrikRoot).getEternalPromise(); p2.catch(() => 'hush'); + const p3 = E(ulrikRoot).getWatchedDecidedPromise(); - return { version, data, p1, p2, retain, ...parameters }; + // Create our own promises that capture the rejection data in a + // way that the test harness can read, because the originals + // will be GCed when the rejection notifications finish + // delivery. + const p1w = Promise.resolve().then(() => p1); + const p2w = Promise.resolve().then(() => p2); + + return { version, data, p1, p2, p3, p1w, p2w, retain, ...parameters }; }, upgradeV2: async () => { @@ -145,8 +153,17 @@ export const buildRootObject = () => { resolve(`message for your predecessor, don't freak out`); const newDur = await E(ulrikRoot).getNewDurandal(); - - return { version, data, remoerr, newDur, upgradeResult, ...parameters }; + const watcherResult = await E(ulrikRoot).getWatcherResult(); + + return { + version, + data, + remoerr, + newDur, + upgradeResult, + watcherResult, + ...parameters, + }; }, buildV1WithLostKind: async () => { diff --git a/packages/SwingSet/test/upgrade/upgrade.test.js b/packages/SwingSet/test/upgrade/upgrade.test.js index aca1efbbd89..85a1b6de7b5 100644 --- a/packages/SwingSet/test/upgrade/upgrade.test.js +++ b/packages/SwingSet/test/upgrade/upgrade.test.js @@ -363,6 +363,11 @@ const testUpgrade = async (t, defaultManagerType, options = {}) => { // grab the promises that should be rejected const v1p1Kref = verifyPresence(v1result.p1); const v1p2Kref = verifyPresence(v1result.p2); + const v1p1wKref = verifyPresence(v1result.p1w); + const v1p2wKref = verifyPresence(v1result.p2w); + const v1p3Kref = verifyPresence(v1result.p3); + c.kpRegisterInterest(v1p1wKref); + c.kpRegisterInterest(v1p2wKref); // grab krefs for the exported durable/virtual objects to check their abandonment const retainedKrefs = objectMap(v1result.retain, obj => verifyPresence(obj)); const retainedNames = 'dur1 vir2 vir5 vir7 vc1 vc3 dc4 rem1 rem2 rem3'.split( @@ -461,16 +466,34 @@ const testUpgrade = async (t, defaultManagerType, options = {}) => { const newDurKref = verifyPresence(v2result.newDur); t.not(newDurKref, dur1Kref); - // the old version's non-durable promises should be rejected - t.is(c.kpStatus(v1p1Kref), 'rejected'); + // The old version's non-durable promises should be rejected. The + // original kpids will be GCed. Bug #9039 failed to GC them. + t.is(kvStore.get(`${v1p1Kref}.refCount`), undefined); + t.is(kvStore.get(`${v1p2Kref}.refCount`), undefined); + t.is(kvStore.get(`${vatID}.c.${v1p1Kref}`), undefined); + t.is(kvStore.get(`${vatID}.c.${v1p2Kref}`), undefined); + t.is(kvStore.get(`${v1p1Kref}.state`), undefined); + t.is(kvStore.get(`${v1p2Kref}.state`), undefined); + // but vat-bootstrap wraps them (with Promise.all() so we can + // examine their rejection data. + t.is(c.kpStatus(v1p1wKref), 'rejected'); const vatUpgradedError = { name: 'vatUpgraded', upgradeMessage: 'test upgrade', incarnationNumber: 0, }; - t.deepEqual(kunser(c.kpResolution(v1p1Kref)), vatUpgradedError); - t.is(c.kpStatus(v1p2Kref), 'rejected'); - t.deepEqual(kunser(c.kpResolution(v1p2Kref)), vatUpgradedError); + t.deepEqual(kunser(c.kpResolution(v1p1wKref)), vatUpgradedError); + t.is(c.kpStatus(v1p2wKref), 'rejected'); + t.deepEqual(kunser(c.kpResolution(v1p2wKref)), vatUpgradedError); + + // The local-promise watcher should have fired. If vat-upgrade is + // too aggressive about removing c-list entries (i.e. it doesn't + // check for self-subscription first), the kernel-provoked + // dispatch.notify won't be delivered, and the new incarnation won't + // fire the durable watcher. + t.deepEqual(v2result.watcherResult, ['reject', vatUpgradedError]); + // and the promise it was watching should be GCed + t.is(kvStore.get(`${v1p3Kref}.refCount`), undefined); // verify export abandonment/garbage collection/etc. // This used to be MUCH more extensive, but GC was cut to the bone diff --git a/packages/SwingSet/test/upgrade/vat-ulrik-1.js b/packages/SwingSet/test/upgrade/vat-ulrik-1.js index 89c08c286df..71f54b02030 100644 --- a/packages/SwingSet/test/upgrade/vat-ulrik-1.js +++ b/packages/SwingSet/test/upgrade/vat-ulrik-1.js @@ -8,6 +8,7 @@ import { defineKind, makeScalarBigMapStore, makeScalarBigWeakMapStore, + watchPromise, } from '@agoric/vat-data'; // we set up a lot of ephemeral, merely-virtual, and durable objects @@ -29,6 +30,20 @@ const holderMethods = { const makeVir = defineKind('virtual', initHolder, holderMethods); const makeDur = defineDurableKind(durandalHandle, initHolder, holderMethods); +const initWatcher = () => harden({ result: ['unresolved'] }); +const watcherMethods = { + onFulfilled: ({ state }, data) => (state.result = harden(['fulfill', data])), + onRejected: ({ state }, reason) => + (state.result = harden(['reject', reason])), + getResult: ({ state }) => state.result, +}; +const watcherHandle = makeKindHandle('watcher'); +const makeWatcher = defineDurableKind( + watcherHandle, + initWatcher, + watcherMethods, +); + // TODO: explore 'export modRetains' // eslint-disable-next-line no-unused-vars let modRetains; @@ -134,6 +149,12 @@ const buildExports = (baggage, imp) => { export const buildRootObject = (_vatPowers, vatParameters, baggage) => { const { promise: p1 } = makePromiseKit(); const { promise: p2 } = makePromiseKit(); + const { promise: p3 } = makePromiseKit(); + const watcher = makeWatcher(); + watchPromise(p3, watcher); + baggage.init('watcher', watcher); + baggage.init('wh', watcherHandle); + let heldPromise; let counter = 0; @@ -165,6 +186,7 @@ export const buildRootObject = (_vatPowers, vatParameters, baggage) => { }, getEternalPromiseInArray: () => [p1], getEternalPromise: () => p2, + getWatchedDecidedPromise: () => p3, makeLostKind: () => { makeKindHandle('unhandled'); diff --git a/packages/SwingSet/test/upgrade/vat-ulrik-2.js b/packages/SwingSet/test/upgrade/vat-ulrik-2.js index e843e2154e3..51412d8c31e 100644 --- a/packages/SwingSet/test/upgrade/vat-ulrik-2.js +++ b/packages/SwingSet/test/upgrade/vat-ulrik-2.js @@ -61,6 +61,18 @@ export const buildRootObject = (_vatPowers, vatParameters, baggage) => { } } + const watcherHandle = baggage.get('wh'); + const initWatcher = () => harden({ result: ['unresolved'] }); + const watcherMethods = { + onFulfilled: ({ state }, data) => + (state.result = harden(['fulfill', data])), + onRejected: ({ state }, reason) => + (state.result = harden(['reject', reason])), + getResult: ({ state }) => state.result, + }; + defineDurableKind(watcherHandle, initWatcher, watcherMethods); + const watcher = baggage.get('watcher'); + const root = Far('root', { getVersion: () => 'v2', getParameters: () => vatParameters, @@ -89,6 +101,7 @@ export const buildRootObject = (_vatPowers, vatParameters, baggage) => { return E(handler).ping(`ping ${counter}`); }, getNewDurandal: () => newDur, + getWatcherResult: () => watcher.getResult(), }); // buildRootObject() is allowed to return a Promise, as long as it fulfills // promptly (we added this in #5246 to allow ZCF to use the async diff --git a/packages/boot/test/bootstrapTests/ec-membership-update.test.ts b/packages/boot/test/bootstrapTests/ec-membership-update.test.ts index 164b7f710e8..3865cb87432 100644 --- a/packages/boot/test/bootstrapTests/ec-membership-update.test.ts +++ b/packages/boot/test/bootstrapTests/ec-membership-update.test.ts @@ -59,6 +59,23 @@ export const makeZoeTestContext = async t => { await EV.vat('bootstrap').consumeItem('vaultFactoryKit'); console.timeLog('DefaultTestContext', 'vaultFactoryKit'); + // replaceElectorate relies on these values from the auction upgrade. Insert + // them manually since this bootstrap test doesn't run the auction upgrade. + const governedKits = await EV.vat('bootstrap').consumeItem( + 'governedContractKits', + ); + const auctioneerKit = await EV.vat('bootstrap').consumeItem('auctioneerKit'); + const auctionInstance = await auctioneerKit.instance; + const aKit = await EV(governedKits).get(auctionInstance); + await EV.vat('bootstrap').produceItem( + 'auctionUpgradeNewInstance', + aKit.instance, + ); + await EV.vat('bootstrap').produceItem( + 'auctionUpgradeNewGovCreator', + aKit.governorCreatorFacet, + ); + // has to be late enough for agoricNames data to have been published const agoricNamesRemotes = makeAgoricNamesRemotesFromFakeStorage(storage); console.timeLog('DefaultTestContext', 'agoricNamesRemotes'); diff --git a/packages/builders/scripts/inter-protocol/updatePriceFeeds.js b/packages/builders/scripts/inter-protocol/updatePriceFeeds.js index 866a4865882..c6a96157abf 100644 --- a/packages/builders/scripts/inter-protocol/updatePriceFeeds.js +++ b/packages/builders/scripts/inter-protocol/updatePriceFeeds.js @@ -1,5 +1,3 @@ -/* global process */ - import { makeHelpers } from '@agoric/deploy-script-support'; import { getManifestForPriceFeeds } from '@agoric/inter-protocol/src/proposals/deploy-price-feeds.js'; @@ -38,14 +36,21 @@ const configurations = { }, }; +const { keys } = Object; +const Usage = `agoric run updatePriceFeed.js ${keys(configurations).join(' | ')}`; /** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */ export const defaultProposalBuilder = async ({ publishRef, install }, opts) => { + const config = configurations[opts.variant]; + if (!config) { + console.error(Usage); + throw Error(Usage); + } return harden({ sourceSpec: '@agoric/inter-protocol/src/proposals/deploy-price-feeds.js', getManifestCall: [ getManifestForPriceFeeds.name, { - ...opts, + ...config, priceAggregatorRef: publishRef( install( '@agoric/inter-protocol/src/price/fluxAggregatorContract.js', @@ -63,26 +68,15 @@ export const defaultProposalBuilder = async ({ publishRef, install }, opts) => { }); }; -const { keys } = Object; -const Usage = `agoric run updatePriceFeed.js ${keys(configurations).join(' | ')}`; - /** @type {import('@agoric/deploy-script-support/src/externalTypes.js').DeployScriptFunction} */ export default async (homeP, endowments) => { const { scriptArgs } = endowments; - assert(scriptArgs, 'expected script args endowment'); - const config = configurations[scriptArgs[0]]; - if (!config) { - console.error(Usage); - process.exit(1); - } - console.log('UPPrices', scriptArgs, config); + const variant = scriptArgs?.[0]; + console.log('updatePriceFeeds', scriptArgs, variant); const { writeCoreEval } = await makeHelpers(homeP, endowments); - const match = scriptArgs[0].match(/UNRELEASED_(.*)/); - const variant = match ? match[1] : scriptArgs; - await writeCoreEval(`gov-price-feeds-${variant}`, (utils, opts) => - defaultProposalBuilder(utils, { ...opts, ...config }), + defaultProposalBuilder(utils, { ...opts, variant }), ); }; diff --git a/packages/cosmic-swingset/src/launch-chain.js b/packages/cosmic-swingset/src/launch-chain.js index c18f5fa5d7c..c8b113d5528 100644 --- a/packages/cosmic-swingset/src/launch-chain.js +++ b/packages/cosmic-swingset/src/launch-chain.js @@ -215,7 +215,7 @@ export async function buildSwingset( } const pendingCoreProposals = await ensureSwingsetInitialized(); - upgradeSwingset(kernelStorage); + const { modified } = upgradeSwingset(kernelStorage); const controller = await makeSwingsetController( kernelStorage, deviceEndowments, @@ -236,6 +236,7 @@ export async function buildSwingset( return { coreProposals: pendingCoreProposals, controller, + kernelHasUpgradeEvents: modified, mb: mailboxDevice, bridgeInbound: bridgeDevice.deliverInbound, timer: timerDevice, @@ -408,6 +409,7 @@ export async function launch({ const { coreProposals: bootstrapCoreProposals, controller, + kernelHasUpgradeEvents, mb, bridgeInbound, timer, @@ -510,6 +512,14 @@ export async function launch({ await commit(); } + async function doKernelUpgradeEvents(inboundNum) { + controller.writeSlogObject({ + type: 'cosmic-swingset-inject-kernel-upgrade-events', + inboundNum, + }); + controller.injectQueuedUpgradeEvents(); + } + async function deliverInbound(sender, messages, ack, inboundNum) { Array.isArray(messages) || Fail`inbound given non-Array: ${messages}`; controller.writeSlogObject({ @@ -629,6 +639,11 @@ export async function launch({ break; } + case ActionType.KERNEL_UPGRADE_EVENTS: { + p = doKernelUpgradeEvents(inboundNum); + break; + } + case ActionType.INSTALL_BUNDLE: { p = installBundle(action.bundle); break; @@ -934,6 +949,22 @@ export async function launch({ await doBootstrap(action); } + // The reboot-time upgradeSwingset() may have generated some + // remediation events that need to be injected at the right + // time (after catchup, before proposals). Push them onto + // runThisBlock before anything else goes there. + if (kernelHasUpgradeEvents) { + isBootstrap || + upgradeDetails || + Fail`Unexpected kernel upgrade events outside of consensus start`; + const txHash = 'x/kernel-upgrade-events'; + const context = { blockHeight, txHash, msgIdx: 0 }; + runThisBlock.push({ + action: { type: ActionType.KERNEL_UPGRADE_EVENTS }, + context, + }); + } + // Concatenate together any pending core proposals from chain bootstrap // with any from this inbound init action, then execute them all. const coreProposals = mergeCoreProposals( diff --git a/packages/inter-protocol/src/proposals/add-auction.js b/packages/inter-protocol/src/proposals/add-auction.js index 89769e4cb25..abecb842390 100644 --- a/packages/inter-protocol/src/proposals/add-auction.js +++ b/packages/inter-protocol/src/proposals/add-auction.js @@ -9,6 +9,7 @@ const trace = makeTracer('NewAuction', true); /** * @typedef {PromiseSpaceOf<{ * auctionUpgradeNewInstance: Instance; + * auctionUpgradeNewGovCreator: any; * newContractGovBundleId: string; * }>} interlockPowers */ @@ -33,12 +34,14 @@ export const addAuction = async ( chainTimerService, economicCommitteeCreatorFacet: electorateCreatorFacet, econCharterKit, + governedContractKits: governedContractKitsP, priceAuthority8400, zoe, }, produce: { auctioneerKit: produceAuctioneerKit, auctionUpgradeNewInstance, + auctionUpgradeNewGovCreator, newContractGovBundleId, }, instance: { @@ -197,7 +200,10 @@ export const addAuction = async ( governedInstance, ); + const governedContractKits = await governedContractKitsP; + governedContractKits.init(kit.instance, kit); auctionUpgradeNewInstance.resolve(governedInstance); + auctionUpgradeNewGovCreator.resolve(kit.governorCreatorFacet); newContractGovBundleId.resolve(contractGovernorBundle.bundleID); }; @@ -211,12 +217,14 @@ export const ADD_AUCTION_MANIFEST = harden({ chainTimerService: true, econCharterKit: true, economicCommitteeCreatorFacet: true, + governedContractKits: true, priceAuthority8400: true, zoe: true, }, produce: { auctioneerKit: true, auctionUpgradeNewInstance: true, + auctionUpgradeNewGovCreator: true, newContractGovBundleId: true, }, instance: { diff --git a/packages/inter-protocol/src/proposals/deploy-price-feeds.js b/packages/inter-protocol/src/proposals/deploy-price-feeds.js index a80c50edf43..f98f62223f2 100644 --- a/packages/inter-protocol/src/proposals/deploy-price-feeds.js +++ b/packages/inter-protocol/src/proposals/deploy-price-feeds.js @@ -222,6 +222,9 @@ export const deployPriceFeeds = async (powers, config) => { ); const { priceAuthorityAdmin, priceAuthority } = powers.consume; + + trace({ oracleAddresses }); + trace({ inBrandNames }); for (const inBrandName of inBrandNames) { const AGORIC_INSTANCE_NAME = oracleBrandFeedName(inBrandName, outBrandName); const brandIn = await ensureOracleBrand(powers, { @@ -263,6 +266,7 @@ export const deployPriceFeeds = async (powers, config) => { options: { scaledPARef }, }); + trace('resolving priceAuthority8400'); // cf. #8400 QuotePayments storage leak powers.produce.priceAuthority8400.resolve(priceAuthority); }; diff --git a/packages/inter-protocol/src/proposals/replaceElectorate.js b/packages/inter-protocol/src/proposals/replaceElectorate.js index ac476113d6a..cb862be5a67 100644 --- a/packages/inter-protocol/src/proposals/replaceElectorate.js +++ b/packages/inter-protocol/src/proposals/replaceElectorate.js @@ -305,24 +305,42 @@ const startNewEconCharter = async ({ return startResult; }; +/** + * @typedef {PromiseSpaceOf<{ + * auctionUpgradeNewInstance: Instance; + * auctionUpgradeNewGovCreator: any; + * }>} interlockPowers + */ + /** * Adds governors to an existing Economic Committee Charter * - * - @param {EconomyBootstrapPowers} powers - The resources and capabilities - * required to start the committee. + * @param {EconomyBootstrapPowers & interlockPowers} powers + * + * - The resources and capabilities required to start the committee. * * @param {{ * options: { * econCharterKit: EconCharterStartResult; * }; - * }} config + * }} options * - Configuration object containing the name and size of the committee. * * @returns {Promise} A promise that resolves once all the governors have * been successfully added to the economic charter */ const addGovernorsToEconCharter = async ( - { consume: { psmKit, governedContractKits, auctioneerKit } }, + { + consume: { + auctionUpgradeNewInstance: auctionUpgradeNewInstanceP, + auctionUpgradeNewGovCreator: auctionUpgradeNewGovCreatorP, + psmKit, + governedContractKits, + }, + produce: { + auctionUpgradeNewGovCreator: auctionUpgradeNewGovCreatorProduce, + }, + }, { options: { econCharterKit } }, ) => { const { creatorFacet: ecCreatorFacet } = E.get(econCharterKit); @@ -334,21 +352,15 @@ const addGovernorsToEconCharter = async ( } const governedContractKitMap = await governedContractKits; - const auctioneerKitObject = await auctioneerKit; for (const { instance, governorCreatorFacet, label, } of governedContractKitMap.values()) { - // `governedContractKitMap` has an old version of the auctioneer kit - // so using `auctioneerKit` instead - if (label === 'auctioneer') { - await E(ecCreatorFacet).addInstance( - auctioneerKitObject.instance, - auctioneerKitObject.governorCreatorFacet, - label, - ); - } else { + // The auctioneer was updated in this same release, getting values directly + // (there might be more than one auctioneer instance, but the others don't + // need to be registered.) + if (label !== 'auctioneer') { await E(ecCreatorFacet).addInstance( instance, governorCreatorFacet, @@ -356,15 +368,29 @@ const addGovernorsToEconCharter = async ( ); } } + + const [auctionUpgradeNewInstance, auctionUpgradeNewGovCreator] = + await Promise.all([ + auctionUpgradeNewInstanceP, + auctionUpgradeNewGovCreatorP, + ]); + // reset after use. auctionUpgradeNewInstance is reset by upgrade-vault.js + auctionUpgradeNewGovCreatorProduce.reset(); + + await E(ecCreatorFacet).addInstance( + auctionUpgradeNewInstance, + auctionUpgradeNewGovCreator, + 'auctioneer', + ); }; /** * Replaces the electorate for governance contracts by creating a new Economic * Committee and updating contracts with the new electorate's creator facet. * - * @param {EconomyBootstrapPowers} permittedPowers - The resources and - * capabilities needed for operations, including access to governance - * contracts and the PSM kit. + * @param {EconomyBootstrapPowers & interlockPowers} permittedPowers - The + * resources and capabilities needed for operations, including access to + * governance contracts and the PSM kit. * @param {{ * options: { * committeeName: string; @@ -459,10 +485,11 @@ export const getManifestForReplaceAllElectorates = async ( manifest: { [replaceAllElectorates.name]: { consume: { + auctionUpgradeNewGovCreator: true, + auctionUpgradeNewInstance: true, psmKit: true, governedContractKits: true, chainStorage: true, - auctioneerKit: true, highPrioritySendersManager: true, namesByAddressAdmin: true, // Rest of these are designed to be widely shared @@ -473,6 +500,7 @@ export const getManifestForReplaceAllElectorates = async ( econCharterKit: true, economicCommitteeKit: true, economicCommitteeCreatorFacet: true, + auctionUpgradeNewGovCreator: true, }, installation: { consume: { diff --git a/packages/inter-protocol/src/proposals/upgrade-vaults.js b/packages/inter-protocol/src/proposals/upgrade-vaults.js index ab516d4bc37..febaa8cfa35 100644 --- a/packages/inter-protocol/src/proposals/upgrade-vaults.js +++ b/packages/inter-protocol/src/proposals/upgrade-vaults.js @@ -39,9 +39,6 @@ export const upgradeVaults = async ( auctionUpgradeNewInstance: auctionUpgradeNewInstanceProducer, newContractGovBundleId: newContractGovBundleIdErasor, }, - instance: { - consume: { auctioneer: auctioneerInstanceP }, - }, }, { options: { VaultFactoryBundle: vaultBundleRef } }, ) => { @@ -52,12 +49,7 @@ export const upgradeVaults = async ( await priceAuthority8400; - const [auctionOldInstance, auctionNewInstance] = await Promise.all([ - auctioneerInstanceP, - auctionUpgradeNewInstance, - ]); - auctionOldInstance !== auctionNewInstance || - Fail`Auction instance didn't change`; + const auctionNewInstance = await auctionUpgradeNewInstance; auctionUpgradeNewInstanceProducer.reset(); const publicFacet = E(zoe).getPublicFacet(auctionNewInstance); /** @type {import('@agoric/inter-protocol/src/auction/scheduler.js').FullSchedule} */ @@ -202,7 +194,6 @@ export const getManifestForUpgradeVaults = async ( auctionUpgradeNewInstance: uV, newContractGovBundleId: uV, }, - instance: { consume: { auctioneer: uV } }, }, }, installations: { VaultFactory: restoreRef(VaultFactoryRef) }, diff --git a/packages/internal/src/action-types.js b/packages/internal/src/action-types.js index f07a3fd5592..30e363f5117 100644 --- a/packages/internal/src/action-types.js +++ b/packages/internal/src/action-types.js @@ -16,3 +16,4 @@ export const WALLET_ACTION = 'WALLET_ACTION'; export const WALLET_SPEND_ACTION = 'WALLET_SPEND_ACTION'; export const INSTALL_BUNDLE = 'INSTALL_BUNDLE'; export const VTRANSFER_IBC_EVENT = 'VTRANSFER_IBC_EVENT'; +export const KERNEL_UPGRADE_EVENTS = 'KERNEL_UPGRADE_EVENTS';