@agoric/solo 0.9.5 → 0.9.6-dev-800c2bb.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Dockerfile CHANGED
@@ -1,5 +1,6 @@
1
1
  ARG TAG=latest
2
- FROM agoric/agoric-sdk:$TAG
2
+ ARG REGISTRY=ghcr.io
3
+ FROM $REGISTRY/agoric/agoric-sdk:$TAG
3
4
 
4
5
  WORKDIR /data/solo
5
6
 
package/jsconfig.json CHANGED
@@ -1,22 +1,10 @@
1
1
  // This file can contain .js-specific Typescript compiler config.
2
2
  {
3
+ "extends": "../../tsconfig.json",
3
4
  "compilerOptions": {
4
- "target": "esnext",
5
- "module": "esnext",
6
-
7
- "noEmit": true,
8
- /*
9
- // The following flags are for creating .d.ts files:
10
- "noEmit": false,
11
- "declaration": true,
12
- "emitDeclarationOnly": true,
13
- */
14
- "downlevelIteration": true,
15
- "strictNullChecks": true,
16
- "moduleResolution": "node",
5
+ "checkJs": false,
17
6
  },
18
7
  "include": [
19
- "exported.js",
20
8
  "public/**/*.js",
21
9
  "src/**/*.js",
22
10
  "test/**/*.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/solo",
3
- "version": "0.9.5",
3
+ "version": "0.9.6-dev-800c2bb.0+800c2bb",
4
4
  "description": "Agoric's Solo vat runner",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,39 +15,40 @@
15
15
  "test:xs": "exit 0",
16
16
  "lint-fix": "yarn lint:eslint --fix",
17
17
  "lint": "run-s --continue-on-error lint:*",
18
- "lint:types": "tsc --maxNodeModuleJsDepth 4 -p jsconfig.json",
18
+ "lint:types": "tsc -p jsconfig.json",
19
19
  "lint:eslint": "eslint ."
20
20
  },
21
21
  "keywords": [],
22
22
  "author": "Agoric",
23
23
  "license": "Apache-2.0",
24
24
  "dependencies": {
25
- "@agoric/access-token": "^0.4.20",
26
- "@agoric/assert": "^0.5.1",
27
- "@agoric/cache": "^0.2.4",
28
- "@agoric/cosmic-swingset": "^0.40.0",
29
- "@agoric/notifier": "^0.5.1",
30
- "@agoric/spawner": "^0.6.5",
31
- "@agoric/store": "^0.8.5",
32
- "@agoric/swing-store": "^0.8.1",
33
- "@agoric/swingset-vat": "^0.31.0",
34
- "@agoric/telemetry": "^0.5.0",
35
- "@agoric/vats": "^0.13.2",
36
- "@agoric/wallet": "^0.17.2",
37
- "@endo/captp": "^2.0.15",
38
- "@endo/eventual-send": "^0.16.5",
39
- "@endo/import-bundle": "^0.2.53",
40
- "@endo/init": "^0.5.49",
41
- "@endo/marshal": "^0.7.5",
42
- "@endo/promise-kit": "^0.2.49",
43
- "agoric": "^0.18.4",
25
+ "@agoric/access-token": "0.4.21-dev-800c2bb.0+800c2bb",
26
+ "@agoric/assert": "0.5.2-dev-800c2bb.0+800c2bb",
27
+ "@agoric/cache": "0.2.5-dev-800c2bb.0+800c2bb",
28
+ "@agoric/cosmic-swingset": "0.40.1-dev-800c2bb.0+800c2bb",
29
+ "@agoric/internal": "0.2.2-dev-800c2bb.0+800c2bb",
30
+ "@agoric/notifier": "0.5.2-dev-800c2bb.0+800c2bb",
31
+ "@agoric/spawner": "0.6.6-dev-800c2bb.0+800c2bb",
32
+ "@agoric/store": "0.8.6-dev-800c2bb.0+800c2bb",
33
+ "@agoric/swing-store": "0.8.2-dev-800c2bb.0+800c2bb",
34
+ "@agoric/swingset-vat": "0.31.1-dev-800c2bb.0+800c2bb",
35
+ "@agoric/telemetry": "0.5.1-dev-800c2bb.0+800c2bb",
36
+ "@agoric/time": "0.2.2-dev-800c2bb.0+800c2bb",
37
+ "@agoric/vats": "0.13.3-dev-800c2bb.0+800c2bb",
38
+ "@agoric/wallet": "0.17.3-dev-800c2bb.0+800c2bb",
39
+ "@endo/captp": "^3.1.1",
40
+ "@endo/eventual-send": "^0.17.2",
41
+ "@endo/import-bundle": "^0.3.4",
42
+ "@endo/init": "^0.5.56",
43
+ "@endo/marshal": "^0.8.5",
44
+ "@endo/promise-kit": "^0.2.56",
45
+ "agoric": "0.18.5-dev-800c2bb.0+800c2bb",
44
46
  "anylogger": "^0.21.0",
45
47
  "deterministic-json": "^1.0.5",
46
48
  "esm": "agoric-labs/esm#Agoric-built",
47
49
  "express": "^4.17.1",
48
50
  "http-proxy-middleware": "^2.0.6",
49
- "import-meta-resolve": "^1.1.1",
50
- "lmdb": "^2.4.5",
51
+ "import-meta-resolve": "^2.2.1",
51
52
  "minimist": "^1.2.0",
52
53
  "morgan": "^1.9.1",
53
54
  "node-fetch": "^2.6.0",
@@ -56,10 +57,10 @@
56
57
  "ws": "^7.2.0"
57
58
  },
58
59
  "devDependencies": {
59
- "@agoric/ertp": "^0.15.5",
60
- "@endo/bundle-source": "^2.3.1",
61
- "ava": "^4.3.1",
62
- "c8": "^7.7.2"
60
+ "@agoric/ertp": "0.15.6-dev-800c2bb.0+800c2bb",
61
+ "@endo/bundle-source": "^2.5.1",
62
+ "ava": "^5.2.0",
63
+ "c8": "^7.13.0"
63
64
  },
64
65
  "publishConfig": {
65
66
  "access": "public"
@@ -74,5 +75,5 @@
74
75
  "timeout": "20m",
75
76
  "workerThreads": false
76
77
  },
77
- "gitHead": "636c850161d29c0368b4dec03c90e2674e8d6479"
78
+ "gitHead": "800c2bbed8ccb1e0fc24481c9f95027f95efc1fb"
78
79
  }
package/public/main.js CHANGED
@@ -85,7 +85,7 @@ function run() {
85
85
  if (j.ok) {
86
86
  return j.res;
87
87
  }
88
- throw new Error(`server error: ${JSON.stringify(j.rej)}`);
88
+ throw Error(`server error: ${JSON.stringify(j.rej)}`);
89
89
  }
90
90
 
91
91
  const protocol = window.location.protocol.replace(/^http/, 'ws');
package/solo-config.json CHANGED
@@ -2,6 +2,11 @@
2
2
  "bootstrap": "bootstrap",
3
3
  "defaultManagerType": "xs-worker",
4
4
  "defaultReapInterval": 1000,
5
+ "bundles":{
6
+ "agoricNames": {
7
+ "sourceSpec": "@agoric/vats/src/vat-agoricNames.js"
8
+ }
9
+ },
5
10
  "vats": {
6
11
  "spawner": {
7
12
  "sourceSpec": "./src/vat-spawner.js"
@@ -16,7 +21,7 @@
16
21
  "sourceSpec": "./src/vat-uploads.js"
17
22
  },
18
23
  "bootstrap": {
19
- "sourceSpec": "@agoric/vats/src/core/boot.js"
24
+ "sourceSpec": "@agoric/vats/src/core/boot-solo.js"
20
25
  }
21
26
  }
22
27
  }
package/src/add-chain.js CHANGED
@@ -5,14 +5,14 @@ import djson from 'deterministic-json';
5
5
  import path from 'path';
6
6
  import fs from 'fs';
7
7
 
8
- import { assert, details as X } from '@agoric/assert';
8
+ import { Fail } from '@agoric/assert';
9
9
  import setGCIIngress from './set-gci-ingress.js';
10
10
 
11
11
  const DEFAULT_CHAIN_CONFIG = 'https://testnet.agoric.com/network-config';
12
12
 
13
13
  /**
14
14
  * @param {string} basedir
15
- * @param {string=} chainConfig
15
+ * @param {string} [chainConfig]
16
16
  * @param {boolean} [force=false]
17
17
  */
18
18
  async function addChain(basedir, chainConfig, force = false) {
@@ -60,8 +60,7 @@ async function addChain(basedir, chainConfig, force = false) {
60
60
 
61
61
  netconf.gci = gci;
62
62
  }
63
-
64
- assert(netconf.gci, X`${url.href} does not contain a "gci" entry`);
63
+ netconf.gci || Fail`${url.href} does not contain a "gci" entry`;
65
64
 
66
65
  const connFile = path.join(basedir, 'connections.json');
67
66
  const conns = JSON.parse(fs.readFileSync(connFile));
package/src/captp.js CHANGED
@@ -1,16 +1,13 @@
1
+ // @ts-check
1
2
  import { E, makeCapTP } from '@endo/captp';
2
3
  import { Far } from '@endo/marshal';
3
4
 
4
- export const getCapTPHandler = (
5
- send,
6
- getLocalBootstrap,
7
- fallback = undefined,
8
- ) => {
9
- let lastEpoch;
5
+ export const getCapTPHandler = (send, getLocalBootstrap, fallback) => {
6
+ let lastEpoch = 0;
10
7
  const chans = new Map();
11
8
  const doFallback = async (method, ...args) => {
12
9
  if (!fallback) {
13
- return harden({});
10
+ return false;
14
11
  }
15
12
  return E(fallback)[method](...args);
16
13
  };
@@ -77,7 +74,7 @@ export const getCapTPHandler = (
77
74
  }
78
75
  const done = await doFallback('onMessage', obj, meta);
79
76
  if (!done) {
80
- console.error(`Could not find handler ${obj.type}`, meta);
77
+ console.error(`Could not find handler ${obj.type}`, obj, meta);
81
78
  }
82
79
  return done;
83
80
  },
@@ -1,4 +1,4 @@
1
- /* global setTimeout Buffer */
1
+ /* global clearTimeout setTimeout Buffer */
2
2
  import path from 'path';
3
3
  import fs from 'fs';
4
4
  import url from 'url';
@@ -11,36 +11,33 @@ import anylogger from 'anylogger';
11
11
  import { makeNotifierKit } from '@agoric/notifier';
12
12
  import { makePromiseKit } from '@endo/promise-kit';
13
13
 
14
- import { assert, details as X } from '@agoric/assert';
14
+ import { assert, Fail } from '@agoric/assert';
15
15
  import {
16
16
  DEFAULT_BATCH_TIMEOUT_MS,
17
17
  makeBatchedDeliver,
18
- } from '@agoric/vats/src/batched-deliver.js';
18
+ } from '@agoric/internal/src/batched-deliver.js';
19
+ import { forever, whileTrue } from '@agoric/internal';
19
20
 
20
21
  const console = anylogger('chain-cosmos-sdk');
21
22
 
22
- // the `agd` tool in our repo is built by 'cd golang/cosmos &&
23
- // make'. It lives in the build tree along with `bin/ag-solo`, in case there are
24
- // multiple checkouts of `agoric-sdk`.
23
+ // the `agd` tool in our repo is built on demand. It lives in the build tree
24
+ // along with `bin/ag-solo`, in case there are multiple checkouts of
25
+ // `agoric-sdk`.
25
26
  export const HELPER = url.fileURLToPath(
26
- new URL('../../../golang/cosmos/build/agd', import.meta.url),
27
+ new URL('../../../bin/agd', import.meta.url),
27
28
  );
28
29
 
29
- const FAUCET_ADDRESS =
30
- 'the appropriate faucet channel on Discord (https://agoric.com/discord)';
31
-
32
30
  // Transaction simulation should be an accurate measure of gas.
33
31
  const GAS_ADJUSTMENT = '1.2';
34
32
 
35
33
  const adviseEgress = egressAddr =>
36
34
  `\
37
35
 
38
-
39
- Send:
40
-
41
- !faucet client ${egressAddr}
42
-
43
- to ${FAUCET_ADDRESS}`;
36
+ Visit https://devnet.faucet.agoric.net/
37
+ enter address: ${egressAddr}
38
+ choose client, ag-solo
39
+ and then Submit.
40
+ `;
44
41
 
45
42
  // Retry if our latest message failed.
46
43
  const INITIAL_SEND_RETRY_DELAY_MS = 1_000;
@@ -176,7 +173,7 @@ export async function connectToChain(
176
173
  async function retryRpcHref(tryOnce) {
177
174
  let rpcHrefIndex = lastGoodRpcHrefIndex;
178
175
  // eslint-disable-next-line no-constant-condition
179
- while (true) {
176
+ for await (const _ of forever) {
180
177
  const thisRpcHref = rpcHrefs[rpcHrefIndex];
181
178
 
182
179
  // tryOnce will either throw if cancelled (which rejects this promise),
@@ -193,6 +190,7 @@ export async function connectToChain(
193
190
  await new Promise(resolve => setTimeout(resolve, 5000));
194
191
  rpcHrefIndex = (rpcHrefIndex + 1) % rpcHrefs.length;
195
192
  }
193
+ throw Error(`Unreachable, but the tools don't know that`);
196
194
  }
197
195
 
198
196
  let goodRpcHref = rpcHrefs[0];
@@ -612,7 +610,7 @@ ${chainID} chain does not yet know of address ${clientAddr}${adviseEgress(
612
610
 
613
611
  const messages = messagePool;
614
612
 
615
- try {
613
+ const tryBody = async () => {
616
614
  totalDeliveries += 1;
617
615
  console.log(
618
616
  `delivering to chain (trips=${totalDeliveries})`,
@@ -661,7 +659,7 @@ ${chainID} chain does not yet know of address ${clientAddr}${adviseEgress(
661
659
 
662
660
  // We just try a single delivery per block.
663
661
  let retry = true;
664
- while (retry) {
662
+ for await (const _ of whileTrue(() => retry)) {
665
663
  retry = false;
666
664
  // eslint-disable-next-line no-await-in-loop
667
665
  const { stderr, stdout } = await runHelper([
@@ -690,11 +688,8 @@ ${chainID} chain does not yet know of address ${clientAddr}${adviseEgress(
690
688
  console.debug(`helper said: ${stdout}`);
691
689
  const out = JSON.parse(stdout);
692
690
 
693
- assert.equal(
694
- out.code,
695
- 0,
696
- X`Unexpected output: ${out.raw_log || stdout.trimRight()}`,
697
- );
691
+ out.code === 0 ||
692
+ Fail`Unexpected output: ${out.raw_log || stdout.trimRight()}`;
698
693
 
699
694
  // Wait for the transaction to be included in a block.
700
695
  const txHash = out.txhash;
@@ -704,7 +699,7 @@ ${chainID} chain does not yet know of address ${clientAddr}${adviseEgress(
704
699
  if (txResult.code) {
705
700
  // eslint-disable-next-line no-use-before-define
706
701
  failedSend(
707
- assert.error(X`Error in tx processing: ${txResult.log}`),
702
+ assert.error(`Error in tx processing: ${txResult.log}`),
708
703
  );
709
704
  }
710
705
  });
@@ -715,11 +710,9 @@ ${chainID} chain does not yet know of address ${clientAddr}${adviseEgress(
715
710
  sequenceNumber += 1n;
716
711
  }
717
712
  }
718
- } finally {
719
- if (tmpInfo) {
720
- await fs.promises.unlink(tmpInfo.path);
721
- }
722
- }
713
+ };
714
+
715
+ await tryBody().finally(() => tmpInfo && fs.promises.unlink(tmpInfo.path));
723
716
  };
724
717
 
725
718
  /**
@@ -728,13 +721,13 @@ ${chainID} chain does not yet know of address ${clientAddr}${adviseEgress(
728
721
  *
729
722
  * It then delivers the mailbox to inbound. There are no optimisations.
730
723
  *
731
- * @param {UpdateCount} [lastMailboxUpdate]
724
+ * @param {bigint} [lastMailboxUpdate]
732
725
  */
733
726
  const recurseEachMailboxUpdate = async (lastMailboxUpdate = undefined) => {
734
727
  const { updateCount, value: mailbox } = await mbNotifier.getUpdateSince(
735
728
  lastMailboxUpdate,
736
729
  );
737
- assert(updateCount, X`${GCI} unexpectedly finished!`);
730
+ updateCount || Fail`${GCI} unexpectedly finished!`;
738
731
  if (mailbox) {
739
732
  const { outbox, ack } = mailbox;
740
733
  // console.info('have mailbox', mailbox);
@@ -780,11 +773,11 @@ ${chainID} chain does not yet know of address ${clientAddr}${adviseEgress(
780
773
  };
781
774
 
782
775
  // This function ensures we only have one outgoing send operation at a time.
783
- /** @type {(lastSendUpdate?: UpdateCount) => Promise<void>} */
776
+ /** @type {(lastSendUpdate?: bigint) => Promise<void>} */
784
777
  const recurseEachSend = async (lastSendUpdate = undefined) => {
785
778
  // See when there is another requested send since our last time.
786
779
  const { updateCount } = await sendNotifier.getUpdateSince(lastSendUpdate);
787
- assert(updateCount, X`Sending unexpectedly finished!`);
780
+ updateCount || Fail`Sending unexpectedly finished!`;
788
781
 
789
782
  await sendFromMessagePool().then(successfulSend, failedSend);
790
783
  recurseEachSend(updateCount);
@@ -813,5 +806,9 @@ ${chainID} chain does not yet know of address ${clientAddr}${adviseEgress(
813
806
 
814
807
  // Now that we've started consuming blocks, tell our caller how to deliver
815
808
  // messages.
816
- return makeBatchedDeliver(deliver, Math.min(DEFAULT_BATCH_TIMEOUT_MS, 2000));
809
+ return makeBatchedDeliver(
810
+ deliver,
811
+ { clearTimeout, setTimeout },
812
+ Math.min(DEFAULT_BATCH_TIMEOUT_MS, 2000),
813
+ );
817
814
  }
package/src/entrypoint.js CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  import '@endo/init/pre-bundle-source.js';
4
4
 
5
- // import lmdb early to work around SES incompatibility
6
- import 'lmdb';
7
-
8
5
  // Needed for legacy plugin support (dapp-oracle, for one).
9
6
  import 'esm';
10
7
 
package/src/outbound.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /* global process */
2
2
  import anylogger from 'anylogger';
3
3
 
4
- import { assert, details as X } from '@agoric/assert';
4
+ import { Fail } from '@agoric/assert';
5
5
 
6
6
  // Limit the debug log length.
7
7
  const SOLO_MAX_DEBUG_LENGTH =
@@ -28,7 +28,7 @@ export function deliver(mbs) {
28
28
  for (const target of Object.getOwnPropertyNames(data)) {
29
29
  if (!knownTargets.has(target)) {
30
30
  log.error(`eek, no delivery method for target`, target);
31
- // eslint-disable-next-line no-continue
31
+
32
32
  continue;
33
33
  }
34
34
  const t = knownTargets.get(target);
@@ -62,7 +62,7 @@ export function deliver(mbs) {
62
62
  }
63
63
 
64
64
  export function addDeliveryTarget(target, deliverator) {
65
- assert(!knownTargets.has(target), X`target ${target} already added`);
65
+ !knownTargets.has(target) || Fail`target ${target} already added`;
66
66
  /** @type {TargetRecord} */
67
67
  const targetRecord = { deliverator, highestSent: 0, highestAck: 0 };
68
68
  knownTargets.set(target, targetRecord);
@@ -1,7 +1,6 @@
1
1
  /* global process */
2
2
  // @ts-check
3
3
  import '@endo/init/pre-bundle-source.js';
4
- import 'lmdb';
5
4
  import '@endo/init';
6
5
 
7
6
  import { parse, stringify } from '@endo/marshal';
@@ -9,7 +8,7 @@ import { makePromiseKit } from '@endo/promise-kit';
9
8
 
10
9
  import '@agoric/cosmic-swingset/src/anylogger-agoric.js';
11
10
  import { connectToFakeChain } from '@agoric/cosmic-swingset/src/sim-chain.js';
12
- import { makeShutdown } from '@agoric/telemetry/src/shutdown.js';
11
+ import { makeShutdown } from '@agoric/internal/src/node/shutdown.js';
13
12
 
14
13
  const { registerShutdown } = makeShutdown(false);
15
14
  registerShutdown(() => process.exit());
package/src/pipe.js CHANGED
@@ -5,7 +5,7 @@ import path from 'path';
5
5
  import { makePromiseKit } from '@endo/promise-kit';
6
6
  import { parse, stringify } from '@endo/marshal';
7
7
 
8
- import { makeShutdown } from '@agoric/telemetry/src/shutdown.js';
8
+ import { makeShutdown } from '@agoric/internal/src/node/shutdown.js';
9
9
 
10
10
  const filename = new URL(import.meta.url).pathname;
11
11
  const dirname = path.dirname(filename);
@@ -10,7 +10,7 @@ export default async function resetState(basedir) {
10
10
  );
11
11
  fs.writeFileSync(mailboxStateFile, `{}\n`);
12
12
  const kernelStateDBDir = path.join(basedir, 'swingset-kernel-state');
13
- const { commit, close } = initSwingStore(kernelStateDBDir);
13
+ const { commit, close } = initSwingStore(kernelStateDBDir).hostStorage;
14
14
  await commit();
15
15
  await close();
16
16
  }
package/src/start.js CHANGED
@@ -16,8 +16,8 @@ import anylogger from 'anylogger';
16
16
  // import connect from 'lotion-connect';
17
17
  // import djson from 'deterministic-json';
18
18
 
19
- import { assert, details as X } from '@agoric/assert';
20
- import { makeSlogSender } from '@agoric/telemetry';
19
+ import { assert, Fail } from '@agoric/assert';
20
+ import { makeSlogSender, tryFlushSlogSender } from '@agoric/telemetry';
21
21
  import {
22
22
  loadSwingsetConfigFile,
23
23
  buildCommand,
@@ -30,8 +30,8 @@ import {
30
30
  buildTimer,
31
31
  } from '@agoric/swingset-vat';
32
32
  import { openSwingStore } from '@agoric/swing-store';
33
- import { makeWithQueue } from '@agoric/vats/src/queue.js';
34
- import { makeShutdown } from '@agoric/telemetry/src/shutdown.js';
33
+ import { makeWithQueue } from '@agoric/internal/src/queue.js';
34
+ import { makeShutdown } from '@agoric/internal/src/node/shutdown.js';
35
35
  import {
36
36
  makeDefaultMeterProvider,
37
37
  getTelemetryProviders,
@@ -129,7 +129,7 @@ const buildSwingset = async (
129
129
  // Ensure they can't traverse out of the plugins prefix.
130
130
  const pluginFile = path.resolve(pluginsPrefix, mod);
131
131
  pluginFile.startsWith(pluginsPrefix) ||
132
- assert.fail(X`Cannot load ${pluginFile} plugin; outside of ${pluginDir}`);
132
+ Fail`Cannot load ${pluginFile} plugin; outside of ${pluginDir}`;
133
133
 
134
134
  // TODO: Detect the module type and use the appropriate loader, just like
135
135
  // `agoric deploy`.
@@ -165,7 +165,7 @@ const buildSwingset = async (
165
165
 
166
166
  const soloEnv = Object.fromEntries(
167
167
  Object.entries(process.env)
168
- .filter(([k]) => k.match(/^SOLO_/)) // narrow to SOLO_ prefixes.
168
+ .filter(([k]) => k.match(/^SOLO_/)) // narrow to SOLO_ prefixes. e.g. SOLO_SLOGFILE
169
169
  .map(([k, v]) => [k.replace(/^SOLO_/, ''), v]), // Replace SOLO_ controls with chain version.
170
170
  );
171
171
  const env = {
@@ -179,8 +179,7 @@ const buildSwingset = async (
179
179
  serviceName: TELEMETRY_SERVICE_NAME,
180
180
  });
181
181
 
182
- const { LMDB_MAP_SIZE, SWING_STORE_TRACE, XSNAP_KEEP_SNAPSHOTS } = env;
183
- const mapSize = (LMDB_MAP_SIZE && parseInt(LMDB_MAP_SIZE, 10)) || undefined;
182
+ const { SWING_STORE_TRACE, XSNAP_KEEP_SNAPSHOTS } = env;
184
183
 
185
184
  const defaultTraceFile = path.resolve(kernelStateDBDir, 'store-trace.log');
186
185
  let swingStoreTraceFile;
@@ -201,15 +200,10 @@ const buildSwingset = async (
201
200
  const keepSnapshots =
202
201
  XSNAP_KEEP_SNAPSHOTS === '1' || XSNAP_KEEP_SNAPSHOTS === 'true';
203
202
 
204
- const { kvStore, streamStore, snapStore, commit } = openSwingStore(
205
- kernelStateDBDir,
206
- { mapSize, traceFile: swingStoreTraceFile, keepSnapshots },
207
- );
208
- const hostStorage = {
209
- kvStore,
210
- streamStore,
211
- snapStore,
212
- };
203
+ const { kernelStorage, hostStorage } = openSwingStore(kernelStateDBDir, {
204
+ traceFile: swingStoreTraceFile,
205
+ keepSnapshots,
206
+ });
213
207
 
214
208
  // Not to be confused with the gas model, this meter is for OpenTelemetry.
215
209
  const metricMeter = metricsProvider.getMeter('ag-solo');
@@ -217,11 +211,11 @@ const buildSwingset = async (
217
211
  metricMeter,
218
212
  });
219
213
 
220
- if (!swingsetIsInitialized(hostStorage)) {
214
+ if (!swingsetIsInitialized(kernelStorage)) {
221
215
  if (defaultManagerType && !config.defaultManagerType) {
222
216
  config.defaultManagerType = defaultManagerType;
223
217
  }
224
- await initializeSwingset(config, argv, hostStorage);
218
+ await initializeSwingset(config, argv, kernelStorage);
225
219
  }
226
220
  const slogSender = await makeSlogSender({
227
221
  stateDir: kernelStateDBDir,
@@ -229,7 +223,7 @@ const buildSwingset = async (
229
223
  env,
230
224
  });
231
225
  const controller = await makeSwingsetController(
232
- hostStorage,
226
+ kernelStorage,
233
227
  deviceEndowments,
234
228
  { env, slogCallbacks, slogSender },
235
229
  );
@@ -243,7 +237,7 @@ const buildSwingset = async (
243
237
  async function saveState() {
244
238
  const ms = JSON.stringify(mbs.exportToData());
245
239
  await atomicReplaceFile(mailboxStateFile, ms);
246
- await commit();
240
+ await hostStorage.commit();
247
241
  }
248
242
 
249
243
  function deliverOutbound() {
@@ -254,17 +248,19 @@ const buildSwingset = async (
254
248
 
255
249
  async function processKernel() {
256
250
  await crankScheduler(policy);
257
- if (swingSetRunning) {
258
- await saveState();
259
- deliverOutbound();
251
+ if (!swingSetRunning) {
252
+ return;
260
253
  }
254
+ await saveState();
255
+ deliverOutbound();
256
+ await tryFlushSlogSender(slogSender, { env, log: console.warn });
261
257
  }
262
258
 
263
259
  // Use the input queue to make sure it doesn't overlap with
264
260
  // other inbound messages.
265
261
  const queuedDeliverInboundToMbx = withInputQueue(
266
262
  async function deliverInboundToMbx(sender, messages, ack) {
267
- assert(Array.isArray(messages), X`inbound given non-Array: ${messages}`);
263
+ Array.isArray(messages) || Fail`inbound given non-Array: ${messages}`;
268
264
  // console.debug(`deliverInboundToMbx`, messages, ack);
269
265
  if (mb.deliverInbound(sender, messages, ack)) {
270
266
  await processKernel();
@@ -365,9 +361,11 @@ const deployWallet = async ({ agWallet, deploys, hostport }) => {
365
361
  // This part only runs if there were wallet deploys to do.
366
362
  const resolvedDeploys = deploys.map(dep => path.resolve(agWallet, dep));
367
363
 
368
- const agoricCli = new URL(
369
- await importMetaResolve('agoric/src/entrypoint.js', import.meta.url),
370
- ).pathname;
364
+ const resolvedUrl = await importMetaResolve(
365
+ 'agoric/src/entrypoint.js',
366
+ import.meta.url,
367
+ );
368
+ const agoricCli = new URL(resolvedUrl).pathname;
371
369
 
372
370
  // Use the same verbosity as our caller did for us.
373
371
  let verbosity;
@@ -414,10 +412,8 @@ const start = async (basedir, argv) => {
414
412
  const rawConnections = JSON.parse(
415
413
  fs.readFileSync(rawConnectionsPath, 'utf8'),
416
414
  );
417
- assert(
418
- Array.isArray(rawConnections),
419
- `Invalid connections.json: must be a JSON array, at ${rawConnectionsPath}`,
420
- );
415
+ Array.isArray(rawConnections) ||
416
+ Fail`Invalid connections.json: must be a JSON array, at ${rawConnectionsPath}`;
421
417
  const homeDirectory = process.cwd();
422
418
  const connections = rawConnections.map(connection => {
423
419
  if (['chain-cosmos-sdk', 'fake-chain'].includes(connection.type)) {
@@ -478,10 +474,12 @@ const start = async (basedir, argv) => {
478
474
  // Remove wallet traces.
479
475
  await unlink('html/wallet').catch(_ => {});
480
476
 
477
+ const packageUrl = await importMetaResolve(
478
+ `${wallet}/package.json`,
479
+ import.meta.url,
480
+ );
481
481
  // Find the wallet.
482
- const pjs = new URL(
483
- await importMetaResolve(`${wallet}/package.json`, import.meta.url),
484
- ).pathname;
482
+ const pjs = new URL(packageUrl).pathname;
485
483
  const { 'agoric-wallet': { htmlBasedir = 'ui/build', deploy = [] } = {} } =
486
484
  JSON.parse(fs.readFileSync(pjs, 'utf-8'));
487
485
 
@@ -520,7 +518,7 @@ const start = async (basedir, argv) => {
520
518
  }
521
519
  case 'http': {
522
520
  log(`adding HTTP/WS listener on ${c.host}:${c.port}`);
523
- assert(!broadcastJSON, X`duplicate type=http in connections.json`);
521
+ !broadcastJSON || Fail`duplicate type=http in connections.json`;
524
522
  hostport = `${c.host}:${c.port}`;
525
523
  broadcastJSON = await makeHTTPListener(
526
524
  basedir,
@@ -534,7 +532,7 @@ const start = async (basedir, argv) => {
534
532
  break;
535
533
  }
536
534
  default: {
537
- assert.fail(X`unknown connection type in ${c}`);
535
+ Fail`unknown connection type in ${c}`;
538
536
  }
539
537
  }
540
538
  }),
package/src/vat-http.js CHANGED
@@ -2,7 +2,7 @@ import { makeNotifierKit } from '@agoric/notifier';
2
2
  import { makeCache } from '@agoric/cache';
3
3
  import { E } from '@endo/eventual-send';
4
4
  import { Far } from '@endo/marshal';
5
- import { assert, details as X } from '@agoric/assert';
5
+ import { Fail } from '@agoric/assert';
6
6
  import { getReplHandler } from '@agoric/vats/src/repl.js';
7
7
  import { makePromiseKit } from '@endo/promise-kit';
8
8
  import { getCapTPHandler } from './captp.js';
@@ -41,7 +41,7 @@ export function buildRootObject(vatPowers) {
41
41
  if (remaining.length === 0) {
42
42
  return firstValue;
43
43
  }
44
- assert(firstValue, X`${first} not found in home`);
44
+ firstValue || Fail`${first} not found in home`;
45
45
  return E(firstValue).lookup(...remaining);
46
46
  };
47
47
  harden(lookup);
@@ -102,14 +102,6 @@ export function buildRootObject(vatPowers) {
102
102
  urlToHandler.set(url, commandHandler);
103
103
  }
104
104
 
105
- const { promise: walletP, resolve: resolveWallet } = makePromiseKit();
106
- const { promise: attMakerP, resolve: resolveAttMaker } = makePromiseKit();
107
- Promise.all([walletP, attMakerP]).then(async ([wallet, attMaker]) => {
108
- const walletAdmin = await E(wallet).getAdminFacet();
109
- // console.debug('introduce', { wallet, walletAdmin, attMaker });
110
- E(walletAdmin).resolveAttMaker(attMaker);
111
- });
112
-
113
105
  return Far('root', {
114
106
  setCommandDevice(d) {
115
107
  commandDevice = d;
@@ -146,8 +138,6 @@ export function buildRootObject(vatPowers) {
146
138
  replObjects.local.wallet = wallet;
147
139
  replObjects.home.wallet = wallet;
148
140
  resolveCacheCooordinator(E(E(wallet).getBridge()).getCacheCoordinator());
149
-
150
- resolveWallet(wallet);
151
141
  },
152
142
 
153
143
  /**
@@ -178,10 +168,6 @@ export function buildRootObject(vatPowers) {
178
168
  ...rest
179
169
  } = decentralObjects;
180
170
  decentralObjects = rest;
181
-
182
- if (decentralObjects.attMaker) {
183
- resolveAttMaker(decentralObjects.attMaker);
184
- }
185
171
  }
186
172
 
187
173
  // TODO: Maybe remove sometime; home object is deprecated.
@@ -242,7 +228,7 @@ export function buildRootObject(vatPowers) {
242
228
 
243
229
  if (dispatcher === 'onMessage') {
244
230
  sendResponse(count, false, { type: 'doesNotUnderstand', obj });
245
- assert.fail(X`No handler for ${url} ${type}`);
231
+ Fail`No handler for ${url} ${type}`;
246
232
  }
247
233
  sendResponse(count, false, true);
248
234
  } catch (rej) {
@@ -1,9 +1,9 @@
1
1
  import { Far } from '@endo/marshal';
2
- import makeScratchPad from './scratch.js';
2
+ import makeScratchPad from '@agoric/internal/src/scratch.js';
3
3
 
4
4
  // This vat contains the private upload scratch pad.
5
5
 
6
- export function buildRootObject(_vatPowers) {
6
+ export function buildRootObject() {
7
7
  const uploads = makeScratchPad();
8
8
 
9
9
  function getUploads() {
package/src/web.js CHANGED
@@ -210,7 +210,8 @@ export async function makeHTTPListener(
210
210
 
211
211
  // accept POST messages as commands.
212
212
  app.post('*', async (req, res) => {
213
- if (!(await validateAccessToken(req))) {
213
+ const valid = await validateAccessToken(req);
214
+ if (!valid) {
214
215
  res.json({ ok: false, rej: 'Unauthorized' });
215
216
  return;
216
217
  }
@@ -225,7 +226,8 @@ export async function makeHTTPListener(
225
226
  });
226
227
 
227
228
  app.get('/connections', async (req, res) => {
228
- if (!(await validateAccessToken(req))) {
229
+ const valid = await validateAccessToken(req);
230
+ if (!valid) {
229
231
  res.json({ ok: false, rej: 'Unauthorized' });
230
232
  return;
231
233
  }
@@ -237,7 +239,8 @@ export async function makeHTTPListener(
237
239
  });
238
240
 
239
241
  app.post('/publish-bundle', async (req, res) => {
240
- if (!(await validateAccessToken(req))) {
242
+ const valid = await validateAccessToken(req);
243
+ if (!valid) {
241
244
  res.json({ ok: false, rej: 'Unauthorized' });
242
245
  return;
243
246
  }
@@ -256,7 +259,8 @@ export async function makeHTTPListener(
256
259
  // GETs (which should return index.html) and WebSocket requests.
257
260
  const wss = new WebSocket.Server({ noServer: true });
258
261
  server.on('upgrade', async (req, socket, head) => {
259
- if (!(await validateAccessToken(req))) {
262
+ const valid = await validateAccessToken(req);
263
+ if (!valid) {
260
264
  socket.destroy();
261
265
  return;
262
266
  }
@@ -352,6 +356,9 @@ export async function makeHTTPListener(
352
356
  try {
353
357
  obj = JSON.parse(message);
354
358
  const res = await inboundCommand(obj, meta, id);
359
+ if (typeof res === 'boolean') {
360
+ return;
361
+ }
355
362
 
356
363
  // eslint-disable-next-line no-use-before-define
357
364
  sendJSON({ ...res, meta });
@@ -367,9 +374,7 @@ export async function makeHTTPListener(
367
374
  wss.on('connection', newChannel);
368
375
 
369
376
  function sendJSON(rawObj) {
370
- const { meta: { channelID } = {} } = rawObj;
371
- const obj = { ...rawObj };
372
- delete obj.meta;
377
+ const { meta: { channelID } = {}, ...obj } = rawObj;
373
378
 
374
379
  // Point-to-point.
375
380
  const c = channels.get(channelID);
@@ -44,7 +44,7 @@ export async function makeFixture(PORT, noisy = false) {
44
44
  /** @type {() => void} */
45
45
  let abortCapTP;
46
46
  ws = new WebSocket(
47
- `ws://localhost:${PORT}/private/captp?accessToken=${accessToken}`,
47
+ `ws://127.0.0.1:${PORT}/private/captp?accessToken=${accessToken}`,
48
48
  {
49
49
  origin: `http://localhost:${PORT}`,
50
50
  },
@@ -107,7 +107,7 @@ export async function makeFixture(PORT, noisy = false) {
107
107
  console.log(buf);
108
108
  }
109
109
  // We only reject if the child exits before CapTP is established.
110
- reject(new Error(`CapTP fixture exited with ${code}`));
110
+ reject(Error(`CapTP fixture exited with ${code}`));
111
111
  });
112
112
  tryConnect(resolve, reject);
113
113
  });
package/test/test-home.js CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js';
4
4
 
5
- import bundleSource from '@endo/bundle-source';
5
+ import bundleSourceAmbient from '@endo/bundle-source';
6
6
  import { AmountMath } from '@agoric/ertp';
7
+ import { TimeMath } from '@agoric/time';
7
8
  import { Stable } from '@agoric/vats/src/tokens.js';
8
9
  import { Far } from '@endo/marshal';
9
10
  import { resolve as importMetaResolve } from 'import-meta-resolve';
@@ -12,20 +13,29 @@ import { makeFixture, E } from './captp-fixture.js';
12
13
 
13
14
  const SOLO_PORT = 7999;
14
15
 
15
- // This runs before all the tests.
16
- let home;
17
- let teardown;
16
+ //#region setup (ambient authority is confined to this region)
18
17
  test.before('setup', async t => {
18
+ const loadBundle = async specifier => {
19
+ const contractUrl = await importMetaResolve(specifier, import.meta.url);
20
+ const contractRoot = new URL(contractUrl).pathname;
21
+ t.log({ contractRoot });
22
+ const bundle = await bundleSourceAmbient(contractRoot);
23
+ return bundle;
24
+ };
19
25
  const { homeP, kill } = await makeFixture(SOLO_PORT, process.env.NOISY);
20
- teardown = kill;
21
- home = await homeP;
26
+ const home = await homeP;
27
+
28
+ t.context = { home, teardown: kill, loadBundle };
29
+
22
30
  t.truthy('ready');
23
31
  });
32
+ //#endregion
24
33
 
25
34
  // Now come the tests that use `home`...
26
35
  // =========================================
27
36
 
28
37
  test.serial('home.board', async t => {
38
+ const { home } = t.context;
29
39
  const { board } = E.get(home);
30
40
  await t.throwsAsync(
31
41
  () => E(board).getValue('board0120'),
@@ -50,6 +60,7 @@ test.serial('home.board', async t => {
50
60
  });
51
61
 
52
62
  test.serial('home.wallet - transfer funds to the feePurse', async t => {
63
+ const { home } = t.context;
53
64
  const { wallet, faucet } = E.get(home);
54
65
  const feePurse = E(faucet).getFeePurse();
55
66
  const feeBrand = await E(feePurse).getAllegedBrand();
@@ -62,16 +73,13 @@ test.serial('home.wallet - transfer funds to the feePurse', async t => {
62
73
  });
63
74
 
64
75
  test.serial('home.wallet - receive zoe invite', async t => {
76
+ const { home, loadBundle } = t.context;
65
77
  const { wallet, zoe, board } = E.get(home);
66
78
 
67
79
  // Setup contract in order to get an invite to use in tests
68
- const contractUrl = await importMetaResolve(
80
+ const bundle = await loadBundle(
69
81
  '@agoric/zoe/src/contracts/automaticRefund.js',
70
- import.meta.url,
71
82
  );
72
- const contractRoot = new URL(contractUrl).pathname;
73
- t.log({ contractRoot });
74
- const bundle = await bundleSource(contractRoot);
75
83
  const installationHandle = await E(zoe).install(bundle);
76
84
  const { creatorInvitation: invite } = await E(zoe).startInstance(
77
85
  installationHandle,
@@ -113,6 +121,7 @@ test.serial('home.wallet - receive zoe invite', async t => {
113
121
  });
114
122
 
115
123
  test.serial('home.wallet - central issuer setup', async t => {
124
+ const { home } = t.context;
116
125
  const { wallet } = E.get(home);
117
126
 
118
127
  // Check that the wallet knows about the central issuer.
@@ -127,6 +136,7 @@ test.serial('home.wallet - central issuer setup', async t => {
127
136
  });
128
137
 
129
138
  test.serial('home.localTimerService makeNotifier', async t => {
139
+ const { home } = t.context;
130
140
  const { localTimerService } = E.get(home);
131
141
  const notifier = E(localTimerService).makeNotifier(1n, 1n);
132
142
  const update1 = await E(notifier).getUpdateSince();
@@ -137,7 +147,7 @@ test.serial('home.localTimerService makeNotifier', async t => {
137
147
 
138
148
  // Tests gets an actual localTimerService, which returns actual times. We
139
149
  // can't verify the actual time, so we compare to make sure it's increasing.
140
- t.truthy(update2.value > update1.value);
150
+ t.truthy(TimeMath.compareAbs(update2.value, update1.value) > 0);
141
151
  });
142
152
 
143
153
  function makeHandler() {
@@ -158,6 +168,7 @@ function makeHandler() {
158
168
  }
159
169
 
160
170
  test.serial('home.localTimerService makeRepeater', async t => {
171
+ const { home } = t.context;
161
172
  const { localTimerService } = E.get(home);
162
173
  const timestamp = await E(localTimerService).getCurrentTimestamp();
163
174
  const repeater = E(localTimerService).makeRepeater(1n, 1n);
@@ -167,12 +178,13 @@ test.serial('home.localTimerService makeRepeater', async t => {
167
178
  await E(notifier).getUpdateSince();
168
179
 
169
180
  t.truthy(handler.getCalls() >= 1);
170
- t.truthy(handler.getArgs()[0] > timestamp);
181
+ t.truthy(TimeMath.compareAbs(handler.getArgs()[0], timestamp) > 0);
171
182
  });
172
183
 
173
184
  // =========================================
174
185
  // This runs after all the tests.
175
186
  test.after.always('teardown', async t => {
187
+ const { teardown } = t.context;
176
188
  await teardown();
177
189
  t.truthy('shutdown');
178
190
  });
package/src/scratch.js DELETED
@@ -1,53 +0,0 @@
1
- import { E } from '@endo/eventual-send';
2
- import { Far } from '@endo/marshal';
3
-
4
- export default function makeScratchPad() {
5
- const map = new Map();
6
-
7
- const keys = async () => {
8
- const keyList = [...map.keys()];
9
- return harden(keyList.sort());
10
- };
11
-
12
- const scratch = Far('scratchPad', {
13
- delete: async keyP => {
14
- const key = await keyP;
15
- map.delete(key);
16
- },
17
- get: async keyP => {
18
- const key = await keyP;
19
- return map.get(key);
20
- },
21
- lookup: (...path) => {
22
- if (path.length === 0) {
23
- return scratch;
24
- }
25
- const [first, ...rest] = path;
26
- const firstValue = E(scratch).get(first);
27
- if (rest.length === 0) {
28
- return firstValue;
29
- }
30
- return E(firstValue).lookup(...rest);
31
- },
32
- // Initialize a key only if it doesn't already exist. Needed for atomicity
33
- // between multiple invocations.
34
- init: async (keyP, objP) => {
35
- const [key, obj] = await Promise.all([keyP, objP]);
36
- if (map.has(key)) {
37
- throw Error(`Scratchpad already has key ${key}`);
38
- }
39
- map.set(key, obj);
40
- return key;
41
- },
42
- keys,
43
- // Legacy alias for `keys`.
44
- list: keys,
45
- set: async (keyP, objP) => {
46
- const [key, obj] = await Promise.all([keyP, objP]);
47
- map.set(key, obj);
48
- return key;
49
- },
50
- });
51
- return scratch;
52
- }
53
- /** @typedef {ReturnType<typeof makeScratchPad>} ScratchPad */