@agoric/cosmic-swingset 0.42.0-upgrade-16-dev-12b78e3.0 → 0.42.0-upgrade-17-dev-a61cdab.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/CHANGELOG.md CHANGED
@@ -3,29 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [0.42.0-u16.1](https://github.com/Agoric/agoric-sdk/compare/@agoric/cosmic-swingset@0.42.0-u16.0...@agoric/cosmic-swingset@0.42.0-u16.1) (2024-07-10)
7
-
8
-
9
- ### Bug Fixes
10
-
11
- * adopt `VTRANSFER_IBC_EVENT` as an action-type ([#9671](https://github.com/Agoric/agoric-sdk/issues/9671)) ([67569d4](https://github.com/Agoric/agoric-sdk/commit/67569d4a2461c5415b3cc33f5faee9070f8d3c2e)), closes [#9670](https://github.com/Agoric/agoric-sdk/issues/9670)
12
- * **vm-config:** always use `init-localchain` and `init-transfer` ([1db4ed6](https://github.com/Agoric/agoric-sdk/commit/1db4ed635299cca315ff349ba8a0f3b26b605bf2))
13
-
14
-
15
-
16
- ## [0.42.0-u16.0](https://github.com/Agoric/agoric-sdk/compare/@agoric/cosmic-swingset@0.41.3...@agoric/cosmic-swingset@0.42.0-u16.0) (2024-07-02)
6
+ ## [0.42.0-u17.0](https://github.com/Agoric/agoric-sdk/compare/@agoric/cosmic-swingset@0.41.3...@agoric/cosmic-swingset@0.42.0-u17.0) (2024-09-17)
17
7
 
18
8
 
19
9
  ### ⚠ BREAKING CHANGES
20
10
 
11
+ * **cosmic-swingset:** Exclude non-consensus configuration from bootstrap vat arguments
21
12
  * **cosmos:** add required export-dir export cmd option
22
13
  * remove deprecated `ag-cosmos-helper`
23
14
 
24
15
  ### Features
25
16
 
17
+ * Add consensus-independent vat snapshot archiving configuration to AG_COSMOS_INIT ([ffc594f](https://github.com/Agoric/agoric-sdk/commit/ffc594f9441a9374646c43b69d289cc560962f64)), closes [#10036](https://github.com/Agoric/agoric-sdk/issues/10036)
18
+ * Add consensus-independent vat snapshot retention configuration to AG_COSMOS_INIT ([a5311b5](https://github.com/Agoric/agoric-sdk/commit/a5311b5a9eb257d4dfb4f18272608f00c1616abb)), closes [#9386](https://github.com/Agoric/agoric-sdk/issues/9386)
19
+ * Add consensus-independent vat transcript archiving configuration to AG_COSMOS_INIT ([d2d5803](https://github.com/Agoric/agoric-sdk/commit/d2d5803baab6e6379d179723244b2e92aac6319a)), closes [#10036](https://github.com/Agoric/agoric-sdk/issues/10036)
20
+ * Add consensus-independent vat transcript span retention configuration to AG_COSMOS_INIT ([3cf6b57](https://github.com/Agoric/agoric-sdk/commit/3cf6b57d9e1968c6197147419d5d177b5c42e62b)), closes [#9174](https://github.com/Agoric/agoric-sdk/issues/9174) [#9386](https://github.com/Agoric/agoric-sdk/issues/9386)
26
21
  * add exporter.getHostKV() API ([eb564f9](https://github.com/Agoric/agoric-sdk/commit/eb564f9635397c0706e1f8255b3e125681e2d031)), closes [#8523](https://github.com/Agoric/agoric-sdk/issues/8523)
27
22
  * Add tooling for standalone performance benchmarks ([058e54a](https://github.com/Agoric/agoric-sdk/commit/058e54aad93c04b57dfb3a411bff85c223ab5dd7))
28
23
  * **agd:** try harder to find cosmic-swingset ([dd547f0](https://github.com/Agoric/agoric-sdk/commit/dd547f0a8057109a0bbe27a814fb3fc403ad3fd1))
24
+ * **cosmic-swingset:** Accept slogfile configuration in AG_COSMOS_INIT messages ([1c72193](https://github.com/Agoric/agoric-sdk/commit/1c72193c54126cff8a35f36b094743a415ab19aa))
29
25
  * **cosmic-swingset:** add begin block check and transaction ([#8432](https://github.com/Agoric/agoric-sdk/issues/8432)) ([a9d113a](https://github.com/Agoric/agoric-sdk/commit/a9d113a09dfd93889ae985533535df53fdc771e7))
30
26
  * **cosmic-swingset:** add JS upgrade plan handler stub ([655133e](https://github.com/Agoric/agoric-sdk/commit/655133ed909b5d632dc033e992214a7b6a1b5ab1))
31
27
  * **cosmic-swingset:** add repair-metadata snapshot restore option ([4fc0113](https://github.com/Agoric/agoric-sdk/commit/4fc01134fab9402d5916f0593728acce4697da9e))
@@ -37,6 +33,9 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
37
33
  * **cosmos:** support core proposals set by upgrade handler ([605eb4b](https://github.com/Agoric/agoric-sdk/commit/605eb4b8f33d7646c3a9084d43ecd51029e12b80))
38
34
  * **cosmos:** wire new swingset port handler ([ea582bf](https://github.com/Agoric/agoric-sdk/commit/ea582bf7738f82d0abe5529ee1ac9f2e117c957a))
39
35
  * new 'boot' package with bootstrap configs ([8e3173b](https://github.com/Agoric/agoric-sdk/commit/8e3173b0b86a3dc90b31164bc4272c54e46a6641))
36
+ * Plumb maxVatsOnline from cosmos-sdk config to JS side of swingset ([50b22be](https://github.com/Agoric/agoric-sdk/commit/50b22be79a2fe62a20666c30d86cc5bb8c4f41b7)), closes [#9574](https://github.com/Agoric/agoric-sdk/issues/9574)
37
+ * Share cosmos-sdk runtime [viper] configuration with the cosmic-swingset VM ([950511e](https://github.com/Agoric/agoric-sdk/commit/950511ef1b9b7520bd3eaf8e97cbc315a945b836)), closes [#9946](https://github.com/Agoric/agoric-sdk/issues/9946)
38
+ * Share cosmos-sdk runtime [viper] configuration with the cosmic-swingset VM ([f8c6d50](https://github.com/Agoric/agoric-sdk/commit/f8c6d50e0f20a523caf0366d0ec7ac8b0a731b8e)), closes [#9946](https://github.com/Agoric/agoric-sdk/issues/9946)
40
39
  * Simple removal of lien primarilly through code search ([#8988](https://github.com/Agoric/agoric-sdk/issues/8988)) ([695c440](https://github.com/Agoric/agoric-sdk/commit/695c440c0f48a3591b15a43665682c5f1ebbad9d))
41
40
  * support `coreProposals.steps` ([80fa3d1](https://github.com/Agoric/agoric-sdk/commit/80fa3d14494706d825f51ac22e1bbf4ec68ce404))
42
41
  * **vat-transfer:** first cut at working proposal ([2864bd5](https://github.com/Agoric/agoric-sdk/commit/2864bd5c12300c3595df9676bcfde894dbe59b29))
@@ -45,17 +44,24 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
45
44
 
46
45
  ### Bug Fixes
47
46
 
47
+ * adopt `VTRANSFER_IBC_EVENT` as an action-type ([#9671](https://github.com/Agoric/agoric-sdk/issues/9671)) ([217005a](https://github.com/Agoric/agoric-sdk/commit/217005a921dcac6928c999e6bfe06330a5947ac5)), closes [#9670](https://github.com/Agoric/agoric-sdk/issues/9670)
48
+ * **cosmic-swingset:** add exportCallback interlock ([6547c83](https://github.com/Agoric/agoric-sdk/commit/6547c8318d83ca58704a4c911608706c25795c68)), closes [#9655](https://github.com/Agoric/agoric-sdk/issues/9655)
49
+ * **cosmic-swingset:** add missing bits for maxVatsOnline ([8c0c177](https://github.com/Agoric/agoric-sdk/commit/8c0c17752f7439db6f7aee9f88be1dedce2a1bf1))
48
50
  * **cosmic-swingset:** backwards param compat in import/export ([bd49484](https://github.com/Agoric/agoric-sdk/commit/bd49484e5777b8675ed3be5e78e46f6a5d89b7db))
51
+ * **cosmic-swingset:** call upgradeSwingset at startup ([c769606](https://github.com/Agoric/agoric-sdk/commit/c7696069d0bebaf039a2f3e1a45ebdd8dc5198a2))
52
+ * **cosmic-swingset:** Exclude non-consensus configuration from bootstrap vat arguments ([08b3abb](https://github.com/Agoric/agoric-sdk/commit/08b3abb4d5ba183a45e84353406e67bbcc00a076)), closes [#9946](https://github.com/Agoric/agoric-sdk/issues/9946)
49
53
  * **cosmic-swingset:** log level for swing-store export ([33c4a51](https://github.com/Agoric/agoric-sdk/commit/33c4a517f079c4ad17c30f9d1d13f181b06f112f))
50
54
  * **cosmic-swingset:** merge `coreProposals` from bootstrap and upgrade plan ([2b38ebc](https://github.com/Agoric/agoric-sdk/commit/2b38ebc378847a878725419db37580405df0a28e))
51
55
  * **cosmic-swingset:** only require vatconfig if uninitialized ([cfb72f3](https://github.com/Agoric/agoric-sdk/commit/cfb72f337cf650f303adfebaeffb1ee9ad0c0a92))
52
56
  * **cosmic-swingset:** only search for the `vatconfig` on init ([b14ca40](https://github.com/Agoric/agoric-sdk/commit/b14ca404ea5bc314f99372a3eba878926f94f679))
57
+ * **cosmic-swingset:** plumbing for maxVatsOnline ([45a759a](https://github.com/Agoric/agoric-sdk/commit/45a759a71c8abc724618a12dfd8ae72552b9783e))
53
58
  * **cosmic-swingset:** send started event before beginning actual export ([3c94159](https://github.com/Agoric/agoric-sdk/commit/3c94159bbe4b27a14eeb27612c4a73afa556c472))
54
59
  * DEBUG harmony ([#8136](https://github.com/Agoric/agoric-sdk/issues/8136)) ([d2ea4b4](https://github.com/Agoric/agoric-sdk/commit/d2ea4b46b9efa61e97eec8711830d9fdd741ca55))
55
- * endow with original unstructured `assert` ([#9514](https://github.com/Agoric/agoric-sdk/issues/9514)) ([ce64840](https://github.com/Agoric/agoric-sdk/commit/ce64840f599ee7b73cbe455cc41eecec3464430a)), closes [#9515](https://github.com/Agoric/agoric-sdk/issues/9515) [#5672](https://github.com/Agoric/agoric-sdk/issues/5672) [#8332](https://github.com/Agoric/agoric-sdk/issues/8332) [#9513](https://github.com/Agoric/agoric-sdk/issues/9513) [#5672](https://github.com/Agoric/agoric-sdk/issues/5672) [#8332](https://github.com/Agoric/agoric-sdk/issues/8332) [#9513](https://github.com/Agoric/agoric-sdk/issues/9513) [#9515](https://github.com/Agoric/agoric-sdk/issues/9515) [#5672](https://github.com/Agoric/agoric-sdk/issues/5672) [#5672](https://github.com/Agoric/agoric-sdk/issues/5672) [#9513](https://github.com/Agoric/agoric-sdk/issues/9513) [#9513](https://github.com/Agoric/agoric-sdk/issues/9513)
60
+ * endow with original unstructured `assert` ([#9514](https://github.com/Agoric/agoric-sdk/issues/9514)) ([f908f89](https://github.com/Agoric/agoric-sdk/commit/f908f89186162df83b540f6aeb1f4c665c3a56b4)), closes [#9515](https://github.com/Agoric/agoric-sdk/issues/9515) [#5672](https://github.com/Agoric/agoric-sdk/issues/5672) [#8332](https://github.com/Agoric/agoric-sdk/issues/8332) [#9513](https://github.com/Agoric/agoric-sdk/issues/9513) [#5672](https://github.com/Agoric/agoric-sdk/issues/5672) [#8332](https://github.com/Agoric/agoric-sdk/issues/8332) [#9513](https://github.com/Agoric/agoric-sdk/issues/9513) [#9515](https://github.com/Agoric/agoric-sdk/issues/9515) [#5672](https://github.com/Agoric/agoric-sdk/issues/5672) [#5672](https://github.com/Agoric/agoric-sdk/issues/5672) [#9513](https://github.com/Agoric/agoric-sdk/issues/9513) [#9513](https://github.com/Agoric/agoric-sdk/issues/9513)
56
61
  * export state-sync snapshot without a DB write-lock ([3bc3799](https://github.com/Agoric/agoric-sdk/commit/3bc37990fd813136dab33dd93a1dcec073b187f9)), closes [#8523](https://github.com/Agoric/agoric-sdk/issues/8523)
57
62
  * **sim-params:** power_flag casing ([66955c1](https://github.com/Agoric/agoric-sdk/commit/66955c1e70b63e6525ea10bc946f7c1a84e1e869))
58
63
  * update for `[@jessie](https://github.com/jessie).js/safe-await-separator` ([94c6b3c](https://github.com/Agoric/agoric-sdk/commit/94c6b3c83a5326594f1e2886ae01d6a703a7a68f))
64
+ * **vm-config:** always use `init-localchain` and `init-transfer` ([870d205](https://github.com/Agoric/agoric-sdk/commit/870d2052ce1ca6778f6afa4396e01d5833b7ef38))
59
65
  * **x/swingset:** switch export/import to replay artifact level ([6ab24b2](https://github.com/Agoric/agoric-sdk/commit/6ab24b299f31affc0a638cc6352678a2c167044c))
60
66
 
61
67
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/cosmic-swingset",
3
- "version": "0.42.0-upgrade-16-dev-12b78e3.0+12b78e3",
3
+ "version": "0.42.0-upgrade-17-dev-a61cdab.0+a61cdab",
4
4
  "description": "Agoric's Cosmos blockchain integration",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,24 +22,25 @@
22
22
  "author": "Agoric",
23
23
  "license": "Apache-2.0",
24
24
  "dependencies": {
25
- "@agoric/assert": "0.6.1-upgrade-16-dev-12b78e3.0+12b78e3",
26
- "@agoric/builders": "0.2.0-upgrade-16-dev-12b78e3.0+12b78e3",
27
- "@agoric/cosmos": "0.35.0-upgrade-16-dev-12b78e3.0+12b78e3",
28
- "@agoric/deploy-script-support": "0.10.4-upgrade-16-dev-12b78e3.0+12b78e3",
29
- "@agoric/internal": "0.4.0-upgrade-16-dev-12b78e3.0+12b78e3",
30
- "@agoric/store": "0.9.3-upgrade-16-dev-12b78e3.0+12b78e3",
31
- "@agoric/swing-store": "0.9.2-upgrade-16-dev-12b78e3.0+12b78e3",
32
- "@agoric/swingset-vat": "0.33.0-upgrade-16-dev-12b78e3.0+12b78e3",
33
- "@agoric/telemetry": "0.6.3-upgrade-16-dev-12b78e3.0+12b78e3",
34
- "@agoric/vm-config": "0.1.1-upgrade-16-dev-12b78e3.0+12b78e3",
35
- "@endo/bundle-source": "^3.2.3",
36
- "@endo/env-options": "^1.1.4",
37
- "@endo/far": "^1.1.2",
38
- "@endo/import-bundle": "^1.1.2",
39
- "@endo/init": "^1.1.2",
40
- "@endo/marshal": "^1.5.0",
41
- "@endo/nat": "^5.0.7",
42
- "@endo/promise-kit": "^1.1.2",
25
+ "@agoric/builders": "0.2.0-upgrade-17-dev-a61cdab.0+a61cdab",
26
+ "@agoric/cosmos": "0.35.0-upgrade-17-dev-a61cdab.0+a61cdab",
27
+ "@agoric/deploy-script-support": "0.10.4-upgrade-17-dev-a61cdab.0+a61cdab",
28
+ "@agoric/internal": "0.4.0-upgrade-17-dev-a61cdab.0+a61cdab",
29
+ "@agoric/store": "0.9.3-upgrade-17-dev-a61cdab.0+a61cdab",
30
+ "@agoric/swing-store": "0.9.2-upgrade-17-dev-a61cdab.0+a61cdab",
31
+ "@agoric/swingset-vat": "0.33.0-upgrade-17-dev-a61cdab.0+a61cdab",
32
+ "@agoric/telemetry": "0.6.3-upgrade-17-dev-a61cdab.0+a61cdab",
33
+ "@agoric/vm-config": "0.1.1-upgrade-17-dev-a61cdab.0+a61cdab",
34
+ "@endo/bundle-source": "^3.4.0",
35
+ "@endo/env-options": "^1.1.6",
36
+ "@endo/errors": "^1.2.5",
37
+ "@endo/far": "^1.1.5",
38
+ "@endo/import-bundle": "^1.2.2",
39
+ "@endo/init": "^1.1.4",
40
+ "@endo/marshal": "^1.5.3",
41
+ "@endo/nat": "^5.0.10",
42
+ "@endo/patterns": "^1.4.3",
43
+ "@endo/promise-kit": "^1.1.5",
43
44
  "@iarna/toml": "^2.2.3",
44
45
  "@opentelemetry/api": "~1.3.0",
45
46
  "@opentelemetry/sdk-metrics": "~1.9.0",
@@ -68,7 +69,7 @@
68
69
  "timeout": "20m"
69
70
  },
70
71
  "typeCoverage": {
71
- "atLeast": 80.49
72
+ "atLeast": 80.53
72
73
  },
73
- "gitHead": "12b78e307e22d0dc0c95f40099300e16655781c4"
74
+ "gitHead": "a61cdabb23bd2c846e003dee7326018a7462a929"
74
75
  }
package/src/chain-main.js CHANGED
@@ -1,16 +1,20 @@
1
1
  // @ts-check
2
2
 
3
- import { resolve as pathResolve } from 'path';
3
+ import path from 'node:path';
4
4
  import v8 from 'node:v8';
5
5
  import process from 'node:process';
6
6
  import fs from 'node:fs';
7
7
  import fsPromises from 'node:fs/promises';
8
- import { performance } from 'perf_hooks';
9
- import { resolve as importMetaResolve } from 'import-meta-resolve';
10
- import tmpfs from 'tmp';
8
+ import { performance } from 'node:perf_hooks';
11
9
  import { fork } from 'node:child_process';
10
+ import { resolve as importMetaResolve } from 'import-meta-resolve';
11
+ import tmp from 'tmp';
12
12
 
13
+ import { Fail, q } from '@endo/errors';
13
14
  import { E } from '@endo/far';
15
+ import { makeMarshal } from '@endo/marshal';
16
+ import { isNat } from '@endo/nat';
17
+ import { M, mustMatch } from '@endo/patterns';
14
18
  import engineGC from '@agoric/internal/src/lib-nodejs/engine-gc.js';
15
19
  import { waitUntilQuiescent } from '@agoric/internal/src/lib-nodejs/waitUntilQuiescent.js';
16
20
  import {
@@ -18,19 +22,21 @@ import {
18
22
  exportMailbox,
19
23
  } from '@agoric/swingset-vat/src/devices/mailbox/mailbox.js';
20
24
 
21
- import { Fail, q } from '@agoric/assert';
22
25
  import { makeSlogSender, tryFlushSlogSender } from '@agoric/telemetry';
23
26
 
24
27
  import {
25
28
  makeChainStorageRoot,
26
29
  makeSerializeToStorage,
27
30
  } from '@agoric/internal/src/lib-chainStorage.js';
28
- import { makeMarshal } from '@endo/marshal';
29
31
  import { makeShutdown } from '@agoric/internal/src/node/shutdown.js';
30
32
 
31
33
  import * as STORAGE_PATH from '@agoric/internal/src/chain-storage-paths.js';
32
34
  import * as ActionType from '@agoric/internal/src/action-types.js';
33
35
  import { BridgeId, CosmosInitKeyToBridgeId } from '@agoric/internal';
36
+ import {
37
+ makeArchiveSnapshot,
38
+ makeArchiveTranscript,
39
+ } from '@agoric/swing-store';
34
40
  import {
35
41
  makeBufferedStorage,
36
42
  makeReadCachingStorage,
@@ -48,6 +54,8 @@ import {
48
54
  validateImporterOptions,
49
55
  } from './import-kernel-db.js';
50
56
 
57
+ const ignore = () => {};
58
+
51
59
  // eslint-disable-next-line no-unused-vars
52
60
  let whenHellFreezesOver = null;
53
61
 
@@ -62,6 +70,66 @@ const toNumber = specimen => {
62
70
  return number;
63
71
  };
64
72
 
73
+ /**
74
+ * The swingset config object parsed and resolved by cosmos in
75
+ * `golang/cosmos/x/swingset/config.go`. The shape should be kept in sync
76
+ * with `SwingsetConfig` defined there.
77
+ *
78
+ * @typedef {object} CosmosSwingsetConfig
79
+ * @property {string} [slogfile]
80
+ * @property {number} [maxVatsOnline]
81
+ * @property {'debug' | 'operational'} [vatSnapshotRetention]
82
+ * @property {'archival' | 'operational'} [vatTranscriptRetention]
83
+ * @property {string} [vatSnapshotArchiveDir]
84
+ * @property {string} [vatTranscriptArchiveDir]
85
+ */
86
+ const SwingsetConfigShape = M.splitRecord(
87
+ // All known properties are optional, but unknown properties are not allowed.
88
+ {},
89
+ {
90
+ slogfile: M.string(),
91
+ maxVatsOnline: M.number(),
92
+ vatSnapshotRetention: M.or('debug', 'operational'),
93
+ vatTranscriptRetention: M.or('archival', 'operational'),
94
+ vatSnapshotArchiveDir: M.string(),
95
+ vatTranscriptArchiveDir: M.string(),
96
+ },
97
+ {},
98
+ );
99
+ const validateSwingsetConfig = swingsetConfig => {
100
+ mustMatch(swingsetConfig, SwingsetConfigShape);
101
+ const { maxVatsOnline } = swingsetConfig;
102
+ maxVatsOnline === undefined ||
103
+ (isNat(maxVatsOnline) && maxVatsOnline > 0) ||
104
+ Fail`maxVatsOnline must be a positive integer`;
105
+ };
106
+
107
+ /**
108
+ * A boot message consists of cosmosInitAction fields that are subject to
109
+ * consensus. See cosmosInitAction in {@link ../../../golang/cosmos/app/app.go}.
110
+ *
111
+ * @param {any} initAction
112
+ */
113
+ const makeBootMsg = initAction => {
114
+ const {
115
+ type,
116
+ blockTime,
117
+ blockHeight,
118
+ chainID,
119
+ params,
120
+ // NB: resolvedConfig is independent of consensus and MUST NOT be included
121
+ supplyCoins,
122
+ } = initAction;
123
+ return {
124
+ type,
125
+ blockTime,
126
+ blockHeight,
127
+ chainID,
128
+ params,
129
+ supplyCoins,
130
+ };
131
+ };
132
+
65
133
  /**
66
134
  * @template {unknown} [T=unknown]
67
135
  * @param {(req: string) => string} call
@@ -99,8 +167,8 @@ const makePrefixedBridgeStorage = (
99
167
  return fromBridgeStringValue(ret);
100
168
  },
101
169
  set: (key, value) => {
102
- const path = `${prefix}${key}`;
103
- const entry = [path, toBridgeStringValue(value)];
170
+ const fullPath = `${prefix}${key}`;
171
+ const entry = [fullPath, toBridgeStringValue(value)];
104
172
  call(
105
173
  stringify({
106
174
  method: setterMethod,
@@ -109,8 +177,8 @@ const makePrefixedBridgeStorage = (
109
177
  );
110
178
  },
111
179
  delete: key => {
112
- const path = `${prefix}${key}`;
113
- const entry = [path];
180
+ const fullPath = `${prefix}${key}`;
181
+ const entry = [fullPath];
114
182
  call(
115
183
  stringify({
116
184
  method: setterMethod,
@@ -214,7 +282,7 @@ export default async function main(progname, args, { env, homedir, agcc }) {
214
282
 
215
283
  const clearChainSends = async () => {
216
284
  // Cosmos should have blocked before calling commit, but wait just in case
217
- await stateSyncExport?.exporter?.onStarted().catch(() => {});
285
+ await stateSyncExport?.exporter?.onStarted().catch(ignore);
218
286
 
219
287
  const chainSends = savedChainSends;
220
288
  savedChainSends = [];
@@ -246,10 +314,33 @@ export default async function main(progname, args, { env, homedir, agcc }) {
246
314
  /** @type {((obj: object) => void) | undefined} */
247
315
  let writeSlogObject;
248
316
 
249
- // the storagePort used to change for every single message. It's defined out
317
+ // In the past, storagePort could change with every message. It's defined out
250
318
  // here so 'sendToChainStorage' can close over the single mutable instance,
251
319
  // when we updated the 'portNums.storage' value each time toSwingSet was called.
252
- async function launchAndInitializeSwingSet(bootMsg) {
320
+ async function launchAndInitializeSwingSet(initAction) {
321
+ const { XSNAP_KEEP_SNAPSHOTS, NODE_HEAP_SNAPSHOTS = -1 } = env;
322
+
323
+ /** @type {CosmosSwingsetConfig} */
324
+ const swingsetConfig = harden(initAction.resolvedConfig || {});
325
+ validateSwingsetConfig(swingsetConfig);
326
+ const {
327
+ slogfile,
328
+ vatSnapshotRetention,
329
+ vatTranscriptRetention,
330
+ vatSnapshotArchiveDir,
331
+ vatTranscriptArchiveDir,
332
+ } = swingsetConfig;
333
+ const keepSnapshots = vatSnapshotRetention
334
+ ? vatSnapshotRetention !== 'operational'
335
+ : ['1', 'true'].includes(XSNAP_KEEP_SNAPSHOTS);
336
+ const keepTranscripts = vatTranscriptRetention
337
+ ? vatTranscriptRetention !== 'operational'
338
+ : false;
339
+
340
+ // As a kludge, back-propagate selected configuration into environment variables.
341
+ // eslint-disable-next-line dot-notation
342
+ if (slogfile) env['SLOGFILE'] = slogfile;
343
+
253
344
  const sendToChainStorage = msg => chainSend(portNums.storage, msg);
254
345
  // this object is used to store the mailbox state.
255
346
  const fromBridgeMailbox = data => {
@@ -363,7 +454,7 @@ export default async function main(progname, args, { env, homedir, agcc }) {
363
454
  };
364
455
 
365
456
  const argv = {
366
- bootMsg,
457
+ bootMsg: makeBootMsg(initAction),
367
458
  };
368
459
  const getVatConfig = async () => {
369
460
  const vatHref = await importMetaResolve(
@@ -384,7 +475,6 @@ export default async function main(progname, args, { env, homedir, agcc }) {
384
475
  serviceName: TELEMETRY_SERVICE_NAME,
385
476
  });
386
477
 
387
- const { XSNAP_KEEP_SNAPSHOTS, NODE_HEAP_SNAPSHOTS = -1 } = env;
388
478
  const slogSender = await makeSlogSender({
389
479
  stateDir: stateDBDir,
390
480
  env,
@@ -394,17 +484,14 @@ export default async function main(progname, args, { env, homedir, agcc }) {
394
484
  const swingStoreTraceFile = processValue.getPath({
395
485
  envName: 'SWING_STORE_TRACE',
396
486
  flagName: 'trace-store',
397
- trueValue: pathResolve(stateDBDir, 'store-trace.log'),
487
+ trueValue: path.resolve(stateDBDir, 'store-trace.log'),
398
488
  });
399
489
 
400
- const keepSnapshots =
401
- XSNAP_KEEP_SNAPSHOTS === '1' || XSNAP_KEEP_SNAPSHOTS === 'true';
402
-
403
490
  const nodeHeapSnapshots = Number.parseInt(NODE_HEAP_SNAPSHOTS, 10);
404
491
 
405
492
  let lastCommitTime = 0;
406
493
  let commitCallsSinceLastSnapshot = NaN;
407
- const snapshotBaseDir = pathResolve(stateDBDir, 'node-heap-snapshots');
494
+ const snapshotBaseDir = path.resolve(stateDBDir, 'node-heap-snapshots');
408
495
 
409
496
  if (nodeHeapSnapshots >= 0) {
410
497
  fs.mkdirSync(snapshotBaseDir, { recursive: true });
@@ -440,7 +527,7 @@ export default async function main(progname, args, { env, homedir, agcc }) {
440
527
  ) {
441
528
  commitCallsSinceLastSnapshot = 0;
442
529
  heapSnapshot = `Heap-${process.pid}-${Date.now()}.heapsnapshot`;
443
- const snapshotPath = pathResolve(snapshotBaseDir, heapSnapshot);
530
+ const snapshotPath = path.resolve(snapshotBaseDir, heapSnapshot);
444
531
  v8.writeHeapSnapshot(snapshotPath);
445
532
  heapSnapshotTime = performance.now() - t3;
446
533
  }
@@ -463,6 +550,14 @@ export default async function main(progname, args, { env, homedir, agcc }) {
463
550
  }
464
551
  };
465
552
 
553
+ const fsPowers = { fs, path, tmp };
554
+ const archiveSnapshot = vatSnapshotArchiveDir
555
+ ? makeArchiveSnapshot(vatSnapshotArchiveDir, fsPowers)
556
+ : undefined;
557
+ const archiveTranscript = vatTranscriptArchiveDir
558
+ ? makeArchiveTranscript(vatTranscriptArchiveDir, fsPowers)
559
+ : undefined;
560
+
466
561
  const s = await launch({
467
562
  actionQueueStorage,
468
563
  highPriorityQueueStorage,
@@ -481,7 +576,11 @@ export default async function main(progname, args, { env, homedir, agcc }) {
481
576
  swingStoreExportCallback,
482
577
  swingStoreTraceFile,
483
578
  keepSnapshots,
579
+ keepTranscripts,
580
+ archiveSnapshot,
581
+ archiveTranscript,
484
582
  afterCommitCallback,
583
+ swingsetConfig,
485
584
  });
486
585
 
487
586
  const { blockingSend, shutdown } = s;
@@ -489,21 +588,19 @@ export default async function main(progname, args, { env, homedir, agcc }) {
489
588
 
490
589
  let pendingBlockingSend = Promise.resolve();
491
590
 
492
- registerShutdown(async interrupted =>
493
- Promise.all([
591
+ registerShutdown(async interrupted => {
592
+ await Promise.all([
494
593
  interrupted && pendingBlockingSend.then(shutdown),
495
594
  discardStateSyncExport(),
496
- ]).then(() => {}),
497
- );
595
+ ]);
596
+ });
498
597
 
499
- return async action => {
598
+ const blockingSendSpy = async action => {
500
599
  const result = blockingSend(action);
501
- pendingBlockingSend = Promise.resolve(result).then(
502
- () => {},
503
- () => {},
504
- );
600
+ pendingBlockingSend = Promise.resolve(result).then(ignore, ignore);
505
601
  return result;
506
602
  };
603
+ return blockingSendSpy;
507
604
  }
508
605
 
509
606
  /** @type {Awaited<ReturnType<typeof launch>>['blockingSend'] | undefined} */
@@ -534,7 +631,7 @@ export default async function main(progname, args, { env, homedir, agcc }) {
534
631
  );
535
632
  return performStateSyncImport(options, {
536
633
  fs: { ...fs, ...fsPromises },
537
- pathResolve,
634
+ pathResolve: path.resolve,
538
635
  log: null,
539
636
  });
540
637
  }
@@ -558,7 +655,7 @@ export default async function main(progname, args, { env, homedir, agcc }) {
558
655
  stateSyncExport = exportData;
559
656
 
560
657
  await new Promise((resolve, reject) => {
561
- tmpfs.dir(
658
+ tmp.dir(
562
659
  {
563
660
  prefix: `agd-state-sync-${blockHeight}-`,
564
661
  unsafeCleanup: true,
@@ -658,6 +755,7 @@ export default async function main(progname, args, { env, homedir, agcc }) {
658
755
 
659
756
  !blockingSend || Fail`Swingset already initialized`;
660
757
 
758
+ // Capture "port numbers" for communicating with cosmos modules.
661
759
  for (const [key, value] of Object.entries(action)) {
662
760
  const portAlias = CosmosInitKeyToBridgeId[key];
663
761
  if (portAlias) {
@@ -10,8 +10,8 @@ import fsPower from 'fs/promises';
10
10
  import pathPower from 'path';
11
11
  import { fileURLToPath } from 'url';
12
12
 
13
+ import { Fail, q } from '@endo/errors';
13
14
  import { makePromiseKit } from '@endo/promise-kit';
14
- import { Fail, q } from '@agoric/assert';
15
15
  import { makeShutdown } from '@agoric/internal/src/node/shutdown.js';
16
16
  import { waitUntilQuiescent } from '@agoric/internal/src/lib-nodejs/waitUntilQuiescent.js';
17
17
  import { makeSwingStoreExporter } from '@agoric/swing-store';
@@ -1,6 +1,6 @@
1
1
  import * as STORAGE_PATH from '@agoric/internal/src/chain-storage-paths.js';
2
2
 
3
- const { Fail, quote: q } = assert;
3
+ import { Fail, q } from '@endo/errors';
4
4
 
5
5
  /**
6
6
  * Export any specified storage subtrees, then delete the ones marked to clear.
@@ -1,6 +1,6 @@
1
1
  // @ts-check
2
2
 
3
- import { assert, Fail } from '@agoric/assert';
3
+ import { assert, Fail } from '@endo/errors';
4
4
 
5
5
  // XXX Do these "StorageAPI" functions belong in their own package?
6
6
 
@@ -1,6 +1,6 @@
1
1
  // @ts-check
2
2
 
3
- import { Fail } from '@agoric/assert';
3
+ import { Fail } from '@endo/errors';
4
4
 
5
5
  /**
6
6
  * @typedef {object} QueueStorage
@@ -11,8 +11,8 @@ import fsPower from 'fs';
11
11
  import fsPromisesPower from 'fs/promises';
12
12
  import pathPower from 'path';
13
13
 
14
+ import { Fail, q } from '@endo/errors';
14
15
  import BufferLineTransform from '@agoric/internal/src/node/buffer-line-transform.js';
15
- import { Fail, q } from '@agoric/assert';
16
16
  import { importSwingStore, openSwingStore } from '@agoric/swing-store';
17
17
 
18
18
  import { isEntrypoint } from './helpers/is-entrypoint.js';
@@ -316,13 +316,13 @@ export function exportKernelStats({
316
316
  }
317
317
  kernelStatsLast = now;
318
318
  kernelStatsCache = controller.getStats();
319
- Object.keys(kernelStatsCache).forEach(key => {
319
+ for (const key of Object.keys(kernelStatsCache)) {
320
320
  warnUnexpectedKernelStat(key);
321
- });
321
+ }
322
322
  return kernelStatsCache;
323
323
  };
324
324
 
325
- KERNEL_STATS_SUM_METRICS.forEach(({ key, name, sub, ...options }) => {
325
+ for (const { key, name, sub, ...options } of KERNEL_STATS_SUM_METRICS) {
326
326
  expectedKernelStats.add(key);
327
327
  let counter = kernelStatsCounters.get(name);
328
328
  if (!counter) {
@@ -337,9 +337,9 @@ export function exportKernelStats({
337
337
  observableResult.observe(getKernelStats()[key], reportedAttributes);
338
338
  });
339
339
  kernelStatsMetrics.add(key);
340
- });
340
+ }
341
341
 
342
- KERNEL_STATS_UPDOWN_METRICS.forEach(({ key, name, sub, ...options }) => {
342
+ for (const { key, name, sub, ...options } of KERNEL_STATS_UPDOWN_METRICS) {
343
343
  expectedKernelStats.add(key);
344
344
  expectedKernelStats.add(`${key}Up`);
345
345
  expectedKernelStats.add(`${key}Down`);
@@ -357,7 +357,7 @@ export function exportKernelStats({
357
357
  observableResult.observe(getKernelStats()[key], reportedAttributes);
358
358
  });
359
359
  kernelStatsMetrics.add(key);
360
- });
360
+ }
361
361
 
362
362
  if (inboundQueueMetrics) {
363
363
  // These are not kernelStatsMetrics, they're outside the kernel.
@@ -425,13 +425,13 @@ export function exportKernelStats({
425
425
 
426
426
  function checkKernelStats(stats) {
427
427
  const notYetFoundKernelStats = new Set(kernelStatsMetrics.keys());
428
- Object.keys(stats).forEach(key => {
428
+ for (const key of Object.keys(stats)) {
429
429
  notYetFoundKernelStats.delete(key);
430
430
  warnUnexpectedKernelStat(key);
431
- });
432
- notYetFoundKernelStats.forEach(key => {
431
+ }
432
+ for (const key of notYetFoundKernelStats) {
433
433
  log.warn(`Expected SwingSet kernel statistic`, key, `not found`);
434
- });
434
+ }
435
435
  }
436
436
 
437
437
  // We check everything on initialization. Other checks happen when scraping.
@@ -7,11 +7,10 @@ import '@agoric/builders';
7
7
 
8
8
  import anylogger from 'anylogger';
9
9
 
10
+ import { assert, Fail } from '@endo/errors';
10
11
  import { E } from '@endo/far';
11
12
  import bundleSource from '@endo/bundle-source';
12
13
 
13
- /** @import {RunPolicy} from '@agoric/swingset-vat' */
14
-
15
14
  import {
16
15
  buildMailbox,
17
16
  buildMailboxStateMap,
@@ -22,9 +21,9 @@ import {
22
21
  makeSwingsetController,
23
22
  loadBasedir,
24
23
  loadSwingsetConfigFile,
24
+ upgradeSwingset,
25
25
  } from '@agoric/swingset-vat';
26
26
  import { waitUntilQuiescent } from '@agoric/internal/src/lib-nodejs/waitUntilQuiescent.js';
27
- import { assert, Fail } from '@agoric/assert';
28
27
  import { openSwingStore } from '@agoric/swing-store';
29
28
  import { BridgeId as BRIDGE_ID } from '@agoric/internal';
30
29
  import { makeWithQueue } from '@agoric/internal/src/queue.js';
@@ -53,6 +52,8 @@ import { makeQueue, makeQueueStorageMock } from './helpers/make-queue.js';
53
52
  import { exportStorage } from './export-storage.js';
54
53
  import { parseLocatedJson } from './helpers/json.js';
55
54
 
55
+ /** @import {RunPolicy} from '@agoric/swingset-vat' */
56
+
56
57
  const console = anylogger('launch-chain');
57
58
  const blockManagerConsole = anylogger('block-manager');
58
59
 
@@ -96,7 +97,7 @@ const getHostKey = path => `host.${path}`;
96
97
 
97
98
  /**
98
99
  * @param {Map<*, *>} mailboxStorage
99
- * @param {undefined | ((dstID: string, obj: any) => any)} bridgeOutbound
100
+ * @param {((dstID: string, obj: any) => any)} bridgeOutbound
100
101
  * @param {SwingStoreKernelStorage} kernelStorage
101
102
  * @param {string | (() => string | Promise<string>)} vatconfig absolute path or thunk
102
103
  * @param {unknown} bootstrapArgs JSON-serializable data
@@ -118,22 +119,21 @@ export async function buildSwingset(
118
119
  verbose,
119
120
  profileVats,
120
121
  debugVats,
122
+ warehousePolicy,
121
123
  },
122
124
  ) {
123
125
  const debugPrefix = debugName === undefined ? '' : `${debugName}:`;
124
126
  const mbs = buildMailboxStateMap(mailboxStorage);
125
127
 
126
- const bridgeDevice = bridgeOutbound && buildBridge(bridgeOutbound);
128
+ const bridgeDevice = buildBridge(bridgeOutbound);
127
129
  const mailboxDevice = buildMailbox(mbs);
128
130
  const timerDevice = buildTimer();
129
131
 
130
132
  const deviceEndowments = {
131
133
  mailbox: { ...mailboxDevice.endowments },
132
134
  timer: { ...timerDevice.endowments },
135
+ bridge: { ...bridgeDevice.endowments },
133
136
  };
134
- if (bridgeDevice) {
135
- deviceEndowments.bridge = { ...bridgeDevice.endowments };
136
- }
137
137
 
138
138
  async function ensureSwingsetInitialized() {
139
139
  if (swingsetIsInitialized(kernelStorage)) {
@@ -175,18 +175,16 @@ export async function buildSwingset(
175
175
  const bootVat =
176
176
  swingsetConfig.vats[swingsetConfig.bootstrap || 'bootstrap'];
177
177
 
178
- if (bridgeOutbound) {
179
- const batchChainStorage = (method, args) =>
180
- bridgeOutbound(BRIDGE_ID.STORAGE, { method, args });
178
+ const batchChainStorage = (method, args) =>
179
+ bridgeOutbound(BRIDGE_ID.STORAGE, { method, args });
181
180
 
182
- // Extract data from chain storage as [path, value?] pairs.
183
- const chainStorageEntries = exportStorage(
184
- batchChainStorage,
185
- exportStorageSubtrees,
186
- clearStorageSubtrees,
187
- );
188
- bootVat.parameters = { ...bootVat.parameters, chainStorageEntries };
189
- }
181
+ // Extract data from chain storage as [path, value?] pairs.
182
+ const chainStorageEntries = exportStorage(
183
+ batchChainStorage,
184
+ exportStorageSubtrees,
185
+ clearStorageSubtrees,
186
+ );
187
+ bootVat.parameters = { ...bootVat.parameters, chainStorageEntries };
190
188
 
191
189
  // Since only on-chain swingsets like `agd` have a bridge (and thereby
192
190
  // `CORE_EVAL` support), things like `ag-solo` will need to do the
@@ -217,7 +215,8 @@ export async function buildSwingset(
217
215
  return bridgedCoreProposals;
218
216
  }
219
217
 
220
- const coreProposals = await ensureSwingsetInitialized();
218
+ const pendingCoreProposals = await ensureSwingsetInitialized();
219
+ upgradeSwingset(kernelStorage);
221
220
  const controller = await makeSwingsetController(
222
221
  kernelStorage,
223
222
  deviceEndowments,
@@ -228,6 +227,7 @@ export async function buildSwingset(
228
227
  verbose,
229
228
  profileVats,
230
229
  debugVats,
230
+ warehousePolicy,
231
231
  },
232
232
  );
233
233
 
@@ -235,10 +235,10 @@ export async function buildSwingset(
235
235
  // (either on bootstrap block (0) or in endBlock).
236
236
 
237
237
  return {
238
- coreProposals,
238
+ coreProposals: pendingCoreProposals,
239
239
  controller,
240
240
  mb: mailboxDevice,
241
- bridgeInbound: bridgeDevice && bridgeDevice.deliverInbound,
241
+ bridgeInbound: bridgeDevice.deliverInbound,
242
242
  timer: timerDevice,
243
243
  };
244
244
  }
@@ -331,10 +331,33 @@ export async function launch({
331
331
  swingStoreTraceFile,
332
332
  swingStoreExportCallback,
333
333
  keepSnapshots,
334
+ keepTranscripts,
335
+ archiveSnapshot,
336
+ archiveTranscript,
334
337
  afterCommitCallback = async () => ({}),
338
+ swingsetConfig,
335
339
  }) {
336
340
  console.info('Launching SwingSet kernel');
337
341
 
342
+ // The swingstore export-data callback gives us export-data records,
343
+ // which must be written into IAVL by sending them over to the
344
+ // golang side with swingStoreExportCallback . However, that
345
+ // callback isn't ready right away, so if e.g. openSwingStore() were
346
+ // to invoke it, we might lose those records. Likewise
347
+ // saveOutsideState() gathers the chainSends just before calling
348
+ // commit, so if the callback were invoked during commit(), those
349
+ // records would be left for a subsequent block, which would break
350
+ // consensus if the node crashed before the next commit. So this
351
+ // `allowExportCallback` flag serves to catch these two cases.
352
+ //
353
+ // Note that swingstore is within its rights to call exportCallback
354
+ // during openSwingStore() or commit(), it just happens to not do so
355
+ // right now. If that changes under maintenance, this guard should
356
+ // turn a corruption bug into a crash bug. See
357
+ // https://github.com/Agoric/agoric-sdk/issues/9655 for details
358
+
359
+ let allowExportCallback = false;
360
+
338
361
  // The swingStore's exportCallback is synchronous, however we allow the
339
362
  // callback provided to launch-chain to be asynchronous. The callbacks are
340
363
  // invoked sequentially like if they were awaited, and the block manager
@@ -345,6 +368,7 @@ export async function launch({
345
368
  const swingStoreExportSyncCallback =
346
369
  swingStoreExportCallback &&
347
370
  (updates => {
371
+ assert(allowExportCallback, 'export-data callback called at bad time');
348
372
  pendingSwingStoreExport = swingStoreExportCallbackWithQueue(updates);
349
373
  });
350
374
 
@@ -352,6 +376,9 @@ export async function launch({
352
376
  traceFile: swingStoreTraceFile,
353
377
  exportCallback: swingStoreExportSyncCallback,
354
378
  keepSnapshots,
379
+ keepTranscripts,
380
+ archiveSnapshot,
381
+ archiveTranscript,
355
382
  });
356
383
  const { kvStore, commit } = hostStorage;
357
384
 
@@ -376,6 +403,9 @@ export async function launch({
376
403
  });
377
404
 
378
405
  console.debug(`buildSwingset`);
406
+ const warehousePolicy = {
407
+ maxVatsOnline: swingsetConfig.maxVatsOnline,
408
+ };
379
409
  const {
380
410
  coreProposals: bootstrapCoreProposals,
381
411
  controller,
@@ -393,6 +423,7 @@ export async function launch({
393
423
  debugName,
394
424
  slogCallbacks,
395
425
  slogSender,
426
+ warehousePolicy,
396
427
  },
397
428
  );
398
429
 
@@ -472,6 +503,7 @@ export async function launch({
472
503
  }
473
504
 
474
505
  async function saveOutsideState(blockHeight) {
506
+ allowExportCallback = false;
475
507
  const chainSends = await clearChainSends();
476
508
  kvStore.set(getHostKey('height'), `${blockHeight}`);
477
509
  kvStore.set(getHostKey('chainSends'), JSON.stringify(chainSends));
@@ -549,8 +581,15 @@ export async function launch({
549
581
  let savedBeginHeight = Number(
550
582
  kvStore.get(getHostKey('beginHeight')) || savedHeight,
551
583
  );
584
+ /**
585
+ * duration of the latest swingset execution in either END_BLOCK or
586
+ * once-per-chain bootstrap (the latter excluding "bridged" core proposals
587
+ * that run outside the bootstrap vat)
588
+ */
552
589
  let runTime = 0;
590
+ /** duration of the latest saveChainState(), which commits mailbox data to chain storage */
553
591
  let chainTime;
592
+ /** duration of the latest saveOutsideState(), which commits to swing-store host storage */
554
593
  let saveTime = 0;
555
594
  let endBlockFinish = 0;
556
595
  let blockParams;
@@ -705,33 +744,16 @@ export async function launch({
705
744
 
706
745
  /**
707
746
  * @template T
708
- * @param {string} type
747
+ * @param {string} label
709
748
  * @param {() => Promise<T>} fn
749
+ * @param {() => void} onSettled
710
750
  */
711
- async function processAction(type, fn) {
712
- const start = Date.now();
713
- const finish = res => {
714
- // blockManagerConsole.error(
715
- // 'Action',
716
- // action.type,
717
- // action.blockHeight,
718
- // 'is done!',
719
- // );
720
- runTime += Date.now() - start;
721
- return res;
722
- };
723
-
751
+ function withErrorLogging(label, fn, onSettled) {
724
752
  const p = fn();
725
- // Just attach some callbacks, but don't use the resulting neutered result
726
- // promise.
727
- void E.when(p, finish, e => {
728
- // None of these must fail, and if they do, log them verbosely before
729
- // returning to the chain.
730
- blockManagerConsole.error(type, 'error:', e);
731
- finish();
753
+ void E.when(p, onSettled, err => {
754
+ blockManagerConsole.error(label, 'error:', err);
755
+ onSettled();
732
756
  });
733
- // Return the original promise so that the caller gets the original
734
- // resolution or rejection.
735
757
  return p;
736
758
  }
737
759
 
@@ -802,8 +824,13 @@ export async function launch({
802
824
  // Start a block transaction, but without changing state
803
825
  // for the upcoming begin block check
804
826
  saveBeginHeight(savedBeginHeight);
805
- await processAction(action.type, async () =>
806
- bootstrapBlock(blockHeight, blockTime, bootstrapBlockParams),
827
+ const start = Date.now();
828
+ await withErrorLogging(
829
+ action.type,
830
+ () => bootstrapBlock(blockHeight, blockTime, bootstrapBlockParams),
831
+ () => {
832
+ runTime += Date.now() - start;
833
+ },
807
834
  );
808
835
  } finally {
809
836
  controller.writeSlogObject({
@@ -891,6 +918,7 @@ export async function launch({
891
918
  // );
892
919
  switch (action.type) {
893
920
  case ActionType.AG_COSMOS_INIT: {
921
+ allowExportCallback = true; // cleared by saveOutsideState in COMMIT_BLOCK
894
922
  const { blockHeight, isBootstrap, upgradeDetails } = action;
895
923
 
896
924
  if (!blockNeedsExecution(blockHeight)) {
@@ -907,17 +935,16 @@ export async function launch({
907
935
  await doBootstrap(action);
908
936
  }
909
937
 
910
- // Merge the core proposals from the bootstrap block with the
911
- // ones from the upgrade.
938
+ // Concatenate together any pending core proposals from chain bootstrap
939
+ // with any from this inbound init action, then execute them all.
912
940
  const coreProposals = mergeCoreProposals(
913
941
  bootstrapCoreProposals,
914
942
  softwareUpgradeCoreProposals,
915
943
  upgradeInfoCoreProposals,
916
944
  );
917
-
918
945
  if (coreProposals.steps.length) {
919
- upgradeDetails ||
920
- isBootstrap ||
946
+ isBootstrap ||
947
+ upgradeDetails ||
921
948
  Fail`Unexpected core proposals outside of consensus start`;
922
949
  await doCoreProposals(action, coreProposals);
923
950
  }
@@ -944,9 +971,9 @@ export async function launch({
944
971
  });
945
972
 
946
973
  // Save the kernel's computed state just before the chain commits.
947
- const start2 = Date.now();
974
+ const start = Date.now();
948
975
  await saveOutsideState(savedHeight);
949
- saveTime = Date.now() - start2;
976
+ saveTime = Date.now() - start;
950
977
 
951
978
  blockParams = undefined;
952
979
 
@@ -977,6 +1004,7 @@ export async function launch({
977
1004
  }
978
1005
 
979
1006
  case ActionType.BEGIN_BLOCK: {
1007
+ allowExportCallback = true; // cleared by saveOutsideState in COMMIT_BLOCK
980
1008
  const { blockHeight, blockTime, params } = action;
981
1009
  blockParams = parseParams(params);
982
1010
  verboseBlocks &&
@@ -1043,14 +1071,19 @@ export async function launch({
1043
1071
 
1044
1072
  provideInstallationPublisher();
1045
1073
 
1046
- await processAction(action.type, async () =>
1047
- endBlock(blockHeight, blockTime, blockParams),
1074
+ const start = Date.now();
1075
+ await withErrorLogging(
1076
+ action.type,
1077
+ () => endBlock(blockHeight, blockTime, blockParams),
1078
+ () => {
1079
+ runTime += Date.now() - start;
1080
+ },
1048
1081
  );
1049
1082
 
1050
1083
  // We write out our on-chain state as a number of chainSends.
1051
- const start = Date.now();
1084
+ const start2 = Date.now();
1052
1085
  await saveChainState();
1053
- chainTime = Date.now() - start;
1086
+ chainTime = Date.now() - start2;
1054
1087
 
1055
1088
  // Advance our saved state variables.
1056
1089
  savedHeight = blockHeight;
package/src/params.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // @ts-check
2
2
  // @jessie-check
3
3
 
4
- import { Fail } from '@agoric/assert';
4
+ import { Fail } from '@endo/errors';
5
5
  import { Nat, isNat } from '@endo/nat';
6
6
 
7
7
  export const stringToNat = s => {
package/src/sim-chain.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /* global process setTimeout clearTimeout */
2
2
  import path from 'path';
3
3
  import fs from 'fs';
4
+ import { Fail } from '@endo/errors';
4
5
  import {
5
6
  importMailbox,
6
7
  exportMailbox,
@@ -11,7 +12,6 @@ import anylogger from 'anylogger';
11
12
  import { makeSlogSender } from '@agoric/telemetry';
12
13
 
13
14
  import { resolve as importMetaResolve } from 'import-meta-resolve';
14
- import { Fail } from '@agoric/assert';
15
15
  import { makeWithQueue } from '@agoric/internal/src/queue.js';
16
16
  import { makeBatchedDeliver } from '@agoric/internal/src/batched-deliver.js';
17
17
  import stringify from './helpers/json-stable-stringify.js';