@agoric/cosmic-swingset 0.41.4-dev-26cd420.0 → 0.41.4-dev-76b2796.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/package.json +12 -12
- package/tools/inquisitor.mjs +84 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/cosmic-swingset",
|
|
3
|
-
"version": "0.41.4-dev-
|
|
3
|
+
"version": "0.41.4-dev-76b2796.0+76b2796",
|
|
4
4
|
"description": "Agoric's Cosmos blockchain integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
"author": "Agoric",
|
|
23
23
|
"license": "Apache-2.0",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@agoric/builders": "0.1.1-dev-
|
|
26
|
-
"@agoric/cosmos": "0.34.2-dev-
|
|
27
|
-
"@agoric/deploy-script-support": "0.10.4-dev-
|
|
28
|
-
"@agoric/internal": "0.3.3-dev-
|
|
29
|
-
"@agoric/store": "0.9.3-dev-
|
|
30
|
-
"@agoric/swing-store": "0.9.2-dev-
|
|
31
|
-
"@agoric/swingset-vat": "0.32.3-dev-
|
|
32
|
-
"@agoric/telemetry": "0.6.3-dev-
|
|
33
|
-
"@agoric/vm-config": "0.1.1-dev-
|
|
25
|
+
"@agoric/builders": "0.1.1-dev-76b2796.0+76b2796",
|
|
26
|
+
"@agoric/cosmos": "0.34.2-dev-76b2796.0+76b2796",
|
|
27
|
+
"@agoric/deploy-script-support": "0.10.4-dev-76b2796.0+76b2796",
|
|
28
|
+
"@agoric/internal": "0.3.3-dev-76b2796.0+76b2796",
|
|
29
|
+
"@agoric/store": "0.9.3-dev-76b2796.0+76b2796",
|
|
30
|
+
"@agoric/swing-store": "0.9.2-dev-76b2796.0+76b2796",
|
|
31
|
+
"@agoric/swingset-vat": "0.32.3-dev-76b2796.0+76b2796",
|
|
32
|
+
"@agoric/telemetry": "0.6.3-dev-76b2796.0+76b2796",
|
|
33
|
+
"@agoric/vm-config": "0.1.1-dev-76b2796.0+76b2796",
|
|
34
34
|
"@endo/bundle-source": "^4.0.0",
|
|
35
35
|
"@endo/env-options": "^1.1.8",
|
|
36
36
|
"@endo/errors": "^1.2.10",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"tmp": "^0.2.1"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@agoric/kmarshal": "0.1.1-dev-
|
|
55
|
+
"@agoric/kmarshal": "0.1.1-dev-76b2796.0+76b2796",
|
|
56
56
|
"ava": "^5.3.0",
|
|
57
57
|
"better-sqlite3": "^9.1.1",
|
|
58
58
|
"c8": "^10.1.3"
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"typeCoverage": {
|
|
84
84
|
"atLeast": 86.88
|
|
85
85
|
},
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "76b2796c08ea5c797f7f3374a1d5d8616e11e6dd"
|
|
87
87
|
}
|
package/tools/inquisitor.mjs
CHANGED
|
@@ -89,7 +89,6 @@ const storeExportAPI = ['getExportRecords', 'getArtifactNames'];
|
|
|
89
89
|
* @property {{name: string, critical: boolean}} options
|
|
90
90
|
*/
|
|
91
91
|
|
|
92
|
-
// TODO: getVatAdminNode('v112') # scan the vatAdmin vom v2.vs.vom.* vrefs for value matching /\b${vatID}\b/
|
|
93
92
|
/**
|
|
94
93
|
* @param {object} opt
|
|
95
94
|
* @param {Database} opt.db
|
|
@@ -102,6 +101,7 @@ export const makeHelpers = ({ db, EV }) => {
|
|
|
102
101
|
const kvGet = key => sqlKVGet.get(key);
|
|
103
102
|
const kvGetJSON = key => JSON.parse(/** @type {string} */ (kvGet(key)));
|
|
104
103
|
|
|
104
|
+
/** @typedef {{key: string, value: string}} KVEntry */
|
|
105
105
|
const sqlKVByRange = db.prepare(
|
|
106
106
|
`SELECT key, value FROM kvStore WHERE key >= :a AND key < :b AND ${[
|
|
107
107
|
'(:keySuffix IS NULL OR substr(key, -length(:keySuffix)) = :keySuffix)',
|
|
@@ -116,9 +116,26 @@ export const makeHelpers = ({ db, EV }) => {
|
|
|
116
116
|
'(:valueGlob IS NULL OR value GLOB :valueGlob)',
|
|
117
117
|
].join(' AND ')}`,
|
|
118
118
|
);
|
|
119
|
-
|
|
119
|
+
/**
|
|
120
|
+
* @template {boolean} Lazy
|
|
121
|
+
* @param {string} keyGlob
|
|
122
|
+
* @param {string} [valueGlob]
|
|
123
|
+
* @param {Lazy} [lazy]
|
|
124
|
+
* @returns {Lazy extends true ? Iterable<KVEntry> : Array<KVEntry>}
|
|
125
|
+
*/
|
|
126
|
+
const kvGlob = (
|
|
127
|
+
keyGlob,
|
|
128
|
+
valueGlob = undefined,
|
|
129
|
+
lazy = /** @type {Lazy} */ (false),
|
|
130
|
+
) => {
|
|
131
|
+
// Glob metasyntax is `*` (any substring), `?` (any one character), and
|
|
132
|
+
// `[$chars]`/`[]$chars]` (any one character from inside the brackets, with
|
|
133
|
+
// a requirement that `]` for matching is only valid immediately after the
|
|
134
|
+
// opening bracket).
|
|
120
135
|
const [_keyPattern, keyPrefix, keyTail, keySuffix] =
|
|
121
|
-
/** @type {string[]} */ (
|
|
136
|
+
/** @type {string[]} */ (
|
|
137
|
+
/^([^*?[]*)((?:(?:[*?]|\[\]?[^\]]*\])([^*?[]*))*)$/.exec(keyGlob)
|
|
138
|
+
);
|
|
122
139
|
let sql = sqlKVByHalfRange;
|
|
123
140
|
/** @type {Record<'a' | 'b' | 'keySuffix' | 'keyGlob' | 'valueGlob', string | null>} */
|
|
124
141
|
const args = {
|
|
@@ -137,7 +154,59 @@ export const makeHelpers = ({ db, EV }) => {
|
|
|
137
154
|
} else {
|
|
138
155
|
console.warn('Warning: Unprefixed searches can be slow');
|
|
139
156
|
}
|
|
140
|
-
return lazy ? sql.iterate(args) : sql.all(args);
|
|
157
|
+
return /** @type {any} */ (lazy ? sql.iterate(args) : sql.all(args));
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// We need a RegExp.escape polyfill at least until our minimum supported
|
|
161
|
+
// Node.js includes it natively, however this is harmless to keep even then.
|
|
162
|
+
// It leaves leading ASCII alphanumerics untouched for readability and uses
|
|
163
|
+
// `\u00##` rather than `\x##` for simplicity, neither of which impact
|
|
164
|
+
// `scanVatStore`.
|
|
165
|
+
const needsEscape =
|
|
166
|
+
/([\^$\\.*+?()[\]{}|/])|[-,=<>#&!%:;@~''``""\s\uD800-\uDFFF]/gu;
|
|
167
|
+
const controlEscapes = {
|
|
168
|
+
'\t': '\\t',
|
|
169
|
+
'\n': '\\n',
|
|
170
|
+
'\v': '\\v',
|
|
171
|
+
'\f': '\\f',
|
|
172
|
+
'\r': '\\r',
|
|
173
|
+
};
|
|
174
|
+
const escapeChar = (ch, simple) => {
|
|
175
|
+
if (simple) return `\\${simple}`;
|
|
176
|
+
if (Object.hasOwn(controlEscapes, ch)) return controlEscapes[ch];
|
|
177
|
+
return ch
|
|
178
|
+
.split('')
|
|
179
|
+
.map(cu => `\\u${cu.charCodeAt(0).toString(16).padStart(4, '0')}`)
|
|
180
|
+
.join('');
|
|
181
|
+
};
|
|
182
|
+
const RegExpEscape = str => str.replace(needsEscape, escapeChar);
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Return entries of a vat's KV store that mention `ref` as a distinct word.
|
|
186
|
+
* `ref` may be a vref such as "o-123", but may also be a value such as "123"
|
|
187
|
+
* or "v123" (that last case being particularly useful for finding a vat admin
|
|
188
|
+
* node in vatAdmin's KV store).
|
|
189
|
+
*
|
|
190
|
+
* @param {string} vatID
|
|
191
|
+
* @param {string} ref
|
|
192
|
+
*/
|
|
193
|
+
const scanVatStore = (vatID, ref) => {
|
|
194
|
+
// Use a glob match to find candidates, then a regular expression to select
|
|
195
|
+
// only those with word boundaries around the ref (e.g., we don't want to
|
|
196
|
+
// consider "o-1234" a match for "o-123").
|
|
197
|
+
const candidates = kvGlob(
|
|
198
|
+
`${vatID}.vs.*`,
|
|
199
|
+
`*${ref.replace(/[*?[]/g, '[$&]')}*`,
|
|
200
|
+
true,
|
|
201
|
+
);
|
|
202
|
+
// The non-capturing group serves no functional purpose; it just improves
|
|
203
|
+
// readability in the event that a debugging session finds itself here.
|
|
204
|
+
const re = RegExp(String.raw`\b(?:${RegExpEscape(ref)})\b`);
|
|
205
|
+
const matches = [];
|
|
206
|
+
for (const entry of candidates) {
|
|
207
|
+
if (entry.value.match(re)) matches.push(entry);
|
|
208
|
+
}
|
|
209
|
+
return matches;
|
|
141
210
|
};
|
|
142
211
|
|
|
143
212
|
/**
|
|
@@ -315,7 +384,16 @@ export const makeHelpers = ({ db, EV }) => {
|
|
|
315
384
|
|
|
316
385
|
return harden({
|
|
317
386
|
runCoreEval,
|
|
318
|
-
stable: {
|
|
387
|
+
stable: {
|
|
388
|
+
db,
|
|
389
|
+
getRefs,
|
|
390
|
+
kvGet,
|
|
391
|
+
kvGetJSON,
|
|
392
|
+
kvGlob,
|
|
393
|
+
scanVatStore,
|
|
394
|
+
vatsByID,
|
|
395
|
+
vatsByName,
|
|
396
|
+
},
|
|
319
397
|
});
|
|
320
398
|
};
|
|
321
399
|
/** @typedef {ReturnType<typeof makeHelpers>} Helpers */
|
|
@@ -820,7 +898,7 @@ May be used interactively, or as a recipient of piped commands, or as a module.
|
|
|
820
898
|
Example commands:
|
|
821
899
|
* stable.db.prepare("SELECT name FROM sqlite_schema WHERE type='table'").pluck().all();
|
|
822
900
|
* stable.db.pragma("table_info(transcriptSpans)");
|
|
823
|
-
* [
|
|
901
|
+
* [vatAdminNodeEntry] = stable.scanVatStore('v2', 'v100');
|
|
824
902
|
* stable.getRefs('o+10', 'v1');
|
|
825
903
|
* board = await EV.vat('bootstrap').consumeItem('board');
|
|
826
904
|
* obj = await EV(board).getValue('board02963');
|