@agoric/deploy-script-support 0.11.0 → 0.11.1-upgrade-23-dev-bd79330.0.bd79330
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/README.md +4 -4
- package/package.json +22 -14
- package/src/assertOfferResult.js +1 -0
- package/src/cachedBundleSpec.js +16 -8
- package/src/control/attenuated-deposit.core.js +55 -0
- package/src/control/chain-info.core.js +187 -0
- package/src/control/contract-control.build.js +27 -0
- package/src/control/contract-control.contract.js +386 -0
- package/src/control/contract-control.core.js +138 -0
- package/src/control/get-upgrade-kit.build.js +28 -0
- package/src/control/get-upgrade-kit.core.js +83 -0
- package/src/control/postal-service.core.js +59 -0
- package/src/coreProposalBehavior.js +7 -12
- package/src/depositInvitation.js +2 -1
- package/src/endo-pieces-contract.js +5 -0
- package/src/externalTypes.js +18 -6
- package/src/extract-proposal.js +10 -5
- package/src/getBundlerMaker.js +6 -2
- package/src/helpers.js +21 -7
- package/src/install.js +7 -2
- package/src/installInPieces.js +1 -1
- package/src/offer.js +18 -11
- package/src/parseCoreEvalArgs.js +5 -1
- package/src/saveIssuer.js +3 -1
- package/src/startInstance.js +5 -8
- package/src/wallet-utils.js +150 -0
- package/src/writeCoreEvalParts.js +34 -10
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file contract-control: install, upgrade, terminate, reset chain-storage,
|
|
3
|
+
* for a contract in a branch of agoricNames / chain-storage.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { makeTracer } from '@agoric/internal/src/debug.js';
|
|
7
|
+
import { Fail, q } from '@endo/errors';
|
|
8
|
+
import { E, passStyleOf } from '@endo/far';
|
|
9
|
+
import { M, objectMap } from '@endo/patterns';
|
|
10
|
+
|
|
11
|
+
const trace = makeTracer('CCtrl');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @import {Zone} from '@agoric/base-zone';
|
|
15
|
+
* @import {ContractStartFunction, StartResult} from '@agoric/zoe/src/zoeService/utils.js';
|
|
16
|
+
* @import {Installation, Instance, IssuerKeywordRecord, ZoeService} from '@agoric/zoe';
|
|
17
|
+
* @import {Remote} from '@agoric/internal';
|
|
18
|
+
* @import {StorageNode} from '@agoric/internal/src/lib-chainStorage.js';
|
|
19
|
+
* @import {Board, NameHubKit} from '@agoric/vats';
|
|
20
|
+
* @import {ERef} from '@agoric/vow';
|
|
21
|
+
* @import {StartedInstanceKitWithLabel, StartUpgradable} from '@agoric/vats/src/core/types.js';
|
|
22
|
+
* @import {StartedInstanceKit} from '@agoric/vats/src/core/types.js';
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {<SF extends ContractStartFunction>(instance: Instance<SF>, privateArgs: Parameters<SF>[1]) => void} UpdatePrivateArgs
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
const IssuerShape = M.remotable('Issuer');
|
|
30
|
+
const InstallationShape = M.remotable('Installation');
|
|
31
|
+
const PublicParts = harden({
|
|
32
|
+
label: M.string(),
|
|
33
|
+
instance: M.remotable('Instance'),
|
|
34
|
+
publicFacet: M.remotable('publicFacet'),
|
|
35
|
+
});
|
|
36
|
+
const BundleIdShape = M.string();
|
|
37
|
+
const VatUpgradeResultsShape = M.splitRecord({ incarnationNumber: M.number() });
|
|
38
|
+
const IssuersShape = M.recordOf(M.string(), IssuerShape);
|
|
39
|
+
const PrivateArgsOverridesShape = M.record();
|
|
40
|
+
|
|
41
|
+
const iface = M.interface('ContractControl', {
|
|
42
|
+
install: M.callWhen(M.string()).returns({
|
|
43
|
+
boardId: M.string(),
|
|
44
|
+
installation: InstallationShape,
|
|
45
|
+
}),
|
|
46
|
+
start: M.callWhen(
|
|
47
|
+
M.splitRecord(
|
|
48
|
+
{ installation: InstallationShape },
|
|
49
|
+
{
|
|
50
|
+
issuers: IssuersShape,
|
|
51
|
+
privateArgsOverrides: PrivateArgsOverridesShape,
|
|
52
|
+
},
|
|
53
|
+
{}, // Refuse unsupported options
|
|
54
|
+
),
|
|
55
|
+
).returns(PublicParts),
|
|
56
|
+
installAndStart: M.callWhen(
|
|
57
|
+
M.splitRecord(
|
|
58
|
+
{ bundleId: BundleIdShape },
|
|
59
|
+
{
|
|
60
|
+
issuers: IssuersShape,
|
|
61
|
+
privateArgsOverrides: PrivateArgsOverridesShape,
|
|
62
|
+
},
|
|
63
|
+
{}, // Refuse unsupported options
|
|
64
|
+
),
|
|
65
|
+
).returns(PublicParts),
|
|
66
|
+
getPublicFacet: M.call().returns(M.remotable('publicFacet')),
|
|
67
|
+
getCreatorFacet: M.call().returns(M.remotable('creatorFacet')),
|
|
68
|
+
upgrade: M.callWhen(
|
|
69
|
+
M.or(
|
|
70
|
+
BundleIdShape, // Backward compat with old signature
|
|
71
|
+
M.splitRecord(
|
|
72
|
+
{ bundleId: BundleIdShape },
|
|
73
|
+
{
|
|
74
|
+
privateArgsOverrides: PrivateArgsOverridesShape,
|
|
75
|
+
},
|
|
76
|
+
{}, // Refuse unsupported options
|
|
77
|
+
),
|
|
78
|
+
),
|
|
79
|
+
).returns(VatUpgradeResultsShape),
|
|
80
|
+
terminate: M.callWhen()
|
|
81
|
+
.optional(
|
|
82
|
+
M.splitRecord(
|
|
83
|
+
{},
|
|
84
|
+
{ message: M.string(), target: M.string(), revoke: M.boolean() },
|
|
85
|
+
{}, // Refuse unsupported options
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
.returns(),
|
|
89
|
+
pruneChainStorage: M.callWhen(
|
|
90
|
+
M.recordOf(M.string(), M.arrayOf(M.string())),
|
|
91
|
+
).returns(M.number()),
|
|
92
|
+
revoke: M.call().returns(),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @param {Zone} zone
|
|
97
|
+
* @param {{
|
|
98
|
+
* agoricNamesAdmin: ERef<NameHubKit['nameAdmin']>,
|
|
99
|
+
* board: ERef<Board>,
|
|
100
|
+
* zoe: ERef<ZoeService>,
|
|
101
|
+
* startUpgradable: ERef<StartUpgradable>,
|
|
102
|
+
* updatePrivateArgs: ERef<UpdatePrivateArgs>
|
|
103
|
+
* }} svcs
|
|
104
|
+
*/
|
|
105
|
+
export const prepareContractControl = (zone, svcs) => {
|
|
106
|
+
/** @template {ContractStartFunction} SF */
|
|
107
|
+
const makeMaker = () =>
|
|
108
|
+
zone.exoClass(
|
|
109
|
+
'ContractControl',
|
|
110
|
+
iface,
|
|
111
|
+
/**
|
|
112
|
+
* Install by bundleId and publish to (the board and) agoricNames,
|
|
113
|
+
* replacing anything that was there before.
|
|
114
|
+
*
|
|
115
|
+
* Former installations can be reached from the board.
|
|
116
|
+
*
|
|
117
|
+
* @param {ContractControlOpts} initial
|
|
118
|
+
*/
|
|
119
|
+
initial => ({
|
|
120
|
+
initialPrivateArgs:
|
|
121
|
+
initial.initialPrivateArgs || initial.kit?.privateArgs,
|
|
122
|
+
kit: undefined,
|
|
123
|
+
...initial,
|
|
124
|
+
revoked: false,
|
|
125
|
+
}),
|
|
126
|
+
{
|
|
127
|
+
/** @param {string} bundleId */
|
|
128
|
+
async install(bundleId) {
|
|
129
|
+
const { name, revoked } = this.state;
|
|
130
|
+
trace(name, 'install', bundleId);
|
|
131
|
+
!revoked || Fail`revoked`;
|
|
132
|
+
const { zoe, board, agoricNamesAdmin } = svcs;
|
|
133
|
+
const installation = await E(zoe).installBundleID(bundleId);
|
|
134
|
+
const installationAdmin =
|
|
135
|
+
E(agoricNamesAdmin).lookupAdmin('installation');
|
|
136
|
+
await E(installationAdmin).update(name, installation);
|
|
137
|
+
const boardId = await E(board).getId(installation);
|
|
138
|
+
trace(name, 'installed', { bundleId, installation, boardId });
|
|
139
|
+
return { boardId, installation };
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Start the contract; publish the instance to (the board and) agoricNames.
|
|
144
|
+
*
|
|
145
|
+
* @throws if already running
|
|
146
|
+
* @param {object} opts
|
|
147
|
+
* @param {Installation<SF>} opts.installation
|
|
148
|
+
* @param {IssuerKeywordRecord} [opts.issuers]
|
|
149
|
+
* @param {Partial<Parameters<SF>[1]>} [opts.privateArgsOverrides]
|
|
150
|
+
*/
|
|
151
|
+
async start({ installation, issuers, privateArgsOverrides }) {
|
|
152
|
+
const { name, storageNode, revoked, initialPrivateArgs } = this.state;
|
|
153
|
+
!revoked || Fail`revoked`;
|
|
154
|
+
!this.state.kit || Fail`${name} already started`;
|
|
155
|
+
const { startUpgradable, board } = svcs;
|
|
156
|
+
const installationId = await E(board).getId(installation);
|
|
157
|
+
trace(name, 'startUpgradable', { installation, installationId });
|
|
158
|
+
const privateArgs = harden({
|
|
159
|
+
...initialPrivateArgs,
|
|
160
|
+
storageNode,
|
|
161
|
+
...privateArgsOverrides,
|
|
162
|
+
});
|
|
163
|
+
const kit = await E(startUpgradable)({
|
|
164
|
+
label: name,
|
|
165
|
+
installation,
|
|
166
|
+
issuerKeywordRecord: issuers,
|
|
167
|
+
// terms: customTerms,
|
|
168
|
+
privateArgs,
|
|
169
|
+
});
|
|
170
|
+
/** @type {StartedInstanceKitWithLabel<SF>} */
|
|
171
|
+
const fullKit = harden({ ...kit, privateArgs });
|
|
172
|
+
trace(name, 'started', objectMap(fullKit, passStyleOf));
|
|
173
|
+
this.state.kit = fullKit;
|
|
174
|
+
|
|
175
|
+
const { agoricNamesAdmin } = svcs;
|
|
176
|
+
const instanceAdmin = E(agoricNamesAdmin).lookupAdmin('instance');
|
|
177
|
+
await E(instanceAdmin).update(name, kit.instance);
|
|
178
|
+
const boardId = await E(board).getId(kit.instance);
|
|
179
|
+
trace(name, 'published', { boardId, installationId });
|
|
180
|
+
|
|
181
|
+
return harden({
|
|
182
|
+
label: name,
|
|
183
|
+
instance: kit.instance,
|
|
184
|
+
publicFacet: kit.publicFacet,
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @param {object} opts
|
|
190
|
+
* @param {string} opts.bundleId
|
|
191
|
+
* @param {IssuerKeywordRecord} [opts.issuers]
|
|
192
|
+
* @param {Partial<Parameters<SF>[1]>} [opts.privateArgsOverrides]
|
|
193
|
+
*/
|
|
194
|
+
async installAndStart({ bundleId, issuers, privateArgsOverrides }) {
|
|
195
|
+
trace(this.state.name, 'installAndStart');
|
|
196
|
+
!this.state.revoked || Fail`revoked`;
|
|
197
|
+
const { self } = this;
|
|
198
|
+
const { installation } = await self.install(bundleId);
|
|
199
|
+
return self.start({
|
|
200
|
+
installation,
|
|
201
|
+
issuers,
|
|
202
|
+
privateArgsOverrides,
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
/** @returns {StartResult<SF>['publicFacet']} */
|
|
207
|
+
getPublicFacet() {
|
|
208
|
+
const { name, revoked, kit } = this.state;
|
|
209
|
+
trace(name, 'getPublicFacet');
|
|
210
|
+
!revoked || Fail`revoked`;
|
|
211
|
+
if (!kit) throw Fail`${q(name)}: no StartedInstanceKit`;
|
|
212
|
+
return kit.publicFacet;
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
/** @returns {StartResult<SF>['creatorFacet']} */
|
|
216
|
+
getCreatorFacet() {
|
|
217
|
+
const { name, revoked, kit } = this.state;
|
|
218
|
+
trace(name, 'getCreatorFacet');
|
|
219
|
+
!revoked || Fail`revoked`;
|
|
220
|
+
if (!kit) throw Fail`${q(name)}: no StartedInstanceKit`;
|
|
221
|
+
return kit.creatorFacet;
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
/** @param {string | {bundleId: string; privateArgsOverrides?: Partial<Parameters<SF>[1]>; }} opts */
|
|
225
|
+
async upgrade(opts) {
|
|
226
|
+
if (typeof opts === 'string') opts = { bundleId: opts };
|
|
227
|
+
const { bundleId, privateArgsOverrides = {} } = opts;
|
|
228
|
+
|
|
229
|
+
const { updatePrivateArgs } = svcs;
|
|
230
|
+
|
|
231
|
+
const { name, revoked, kit, initialPrivateArgs } = this.state;
|
|
232
|
+
trace(name, 'upgrade', bundleId);
|
|
233
|
+
!revoked || Fail`revoked`;
|
|
234
|
+
if (!kit) throw Fail`${q(name)}: no StartedInstanceKit`;
|
|
235
|
+
const { privateArgs: previousPrivateArgs } = kit;
|
|
236
|
+
const privateArgs = {
|
|
237
|
+
...initialPrivateArgs,
|
|
238
|
+
...previousPrivateArgs,
|
|
239
|
+
...privateArgsOverrides,
|
|
240
|
+
};
|
|
241
|
+
const result = await E(kit.adminFacet).upgradeContract(
|
|
242
|
+
bundleId,
|
|
243
|
+
privateArgs,
|
|
244
|
+
);
|
|
245
|
+
const newKit = harden({ ...kit, privateArgs });
|
|
246
|
+
trace(name, 'upgrade result', result);
|
|
247
|
+
this.state.kit = newKit;
|
|
248
|
+
await E(updatePrivateArgs)(kit.instance, privateArgs);
|
|
249
|
+
return result;
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @param {object} opts
|
|
254
|
+
* @param {string} [opts.target] boardId to confirm is current
|
|
255
|
+
* @param {string} [opts.message] for termination error
|
|
256
|
+
* @param {boolean} [opts.revoke] neuter this object
|
|
257
|
+
*/
|
|
258
|
+
async terminate(opts = {}) {
|
|
259
|
+
const { name, kit, revoked } = this.state;
|
|
260
|
+
trace(name, 'terminate', kit?.adminFacet, opts);
|
|
261
|
+
!revoked || Fail`revoked`;
|
|
262
|
+
const { target, message = 'terminated', revoke } = opts;
|
|
263
|
+
if (!kit) {
|
|
264
|
+
if (revoke) {
|
|
265
|
+
trace(name, 'revoked');
|
|
266
|
+
this.state.revoked = true;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
throw Fail`${q(name)}: no StartedInstanceKit`;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
await null;
|
|
273
|
+
if (target) {
|
|
274
|
+
const current = await E(svcs.board).getId(kit.instance);
|
|
275
|
+
assert.equal(current, target);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
await E(kit.adminFacet).terminateContract(harden(Error(message)));
|
|
280
|
+
} catch (err) {
|
|
281
|
+
console.error('terminateContract failed; forgetting kit', err);
|
|
282
|
+
}
|
|
283
|
+
this.state.kit = undefined;
|
|
284
|
+
if (revoke) {
|
|
285
|
+
trace(name, 'revoked');
|
|
286
|
+
this.state.revoked = true;
|
|
287
|
+
}
|
|
288
|
+
const { agoricNamesAdmin } = svcs;
|
|
289
|
+
const instanceAdmin = E(agoricNamesAdmin).lookupAdmin('instance');
|
|
290
|
+
await E(instanceAdmin).delete(name);
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
/** @param {Record<string, string[]>} parentToChildren */
|
|
294
|
+
async pruneChainStorage(parentToChildren) {
|
|
295
|
+
const { name, storageNode, revoked } = this.state;
|
|
296
|
+
trace(
|
|
297
|
+
name,
|
|
298
|
+
'pruneChainStorage',
|
|
299
|
+
Object.keys(parentToChildren).length,
|
|
300
|
+
);
|
|
301
|
+
!revoked || Fail`revoked`;
|
|
302
|
+
|
|
303
|
+
/** @param {string[]} path */
|
|
304
|
+
const makePathNode = path => {
|
|
305
|
+
/** @type {Promise<Remote<StorageNode>>} */
|
|
306
|
+
let node = Promise.resolve(storageNode);
|
|
307
|
+
for (const segment of path) {
|
|
308
|
+
node = E(node).makeChildNode(segment);
|
|
309
|
+
}
|
|
310
|
+
return node;
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const prefix = await E(storageNode).getPath();
|
|
314
|
+
for (const parent of Object.keys(parentToChildren)) {
|
|
315
|
+
parent.startsWith(prefix) ||
|
|
316
|
+
Fail`${parent} must start with ${prefix}`;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
let qty = 0;
|
|
320
|
+
for (const [parent, children] of Object.entries(parentToChildren)) {
|
|
321
|
+
trace(name, 'pruning', parent, children);
|
|
322
|
+
const suffix = parent.slice(prefix.length + '.'.length);
|
|
323
|
+
const segments = suffix ? suffix.split('.') : [];
|
|
324
|
+
const parentNode = makePathNode(segments);
|
|
325
|
+
// on failure, trace rather than aborting the whole job
|
|
326
|
+
await Promise.allSettled(
|
|
327
|
+
children.map(async k => {
|
|
328
|
+
await null;
|
|
329
|
+
try {
|
|
330
|
+
await E(
|
|
331
|
+
E(parentNode).makeChildNode(k, { sequence: false }),
|
|
332
|
+
).setValue('');
|
|
333
|
+
qty += 1;
|
|
334
|
+
} catch (err) {
|
|
335
|
+
trace('rejected:', parent, k, err);
|
|
336
|
+
}
|
|
337
|
+
}),
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
trace('done');
|
|
341
|
+
return qty;
|
|
342
|
+
},
|
|
343
|
+
|
|
344
|
+
revoke() {
|
|
345
|
+
const { name, kit, revoked } = this.state;
|
|
346
|
+
trace(name, 'revoke', kit?.adminFacet);
|
|
347
|
+
!revoked || Fail`revoked`;
|
|
348
|
+
|
|
349
|
+
trace(name, 'revoked');
|
|
350
|
+
this.state.revoked = true;
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* @template {ContractStartFunction} [SF=ContractStartFunction]
|
|
357
|
+
* @typedef {ReturnType<ReturnType<typeof makeMaker<SF>>>} ContractControl
|
|
358
|
+
*/
|
|
359
|
+
|
|
360
|
+
/** @type {<SF extends ContractStartFunction>(initial: ContractControlOpts<SF>) => ContractControl<SF>} */
|
|
361
|
+
const makeContractControl = makeMaker();
|
|
362
|
+
|
|
363
|
+
return makeContractControl;
|
|
364
|
+
};
|
|
365
|
+
harden(prepareContractControl);
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* @template {ContractStartFunction} [SF=ContractStartFunction]
|
|
369
|
+
* @typedef {object} ContractControlOpts
|
|
370
|
+
* @property {string} name contractName
|
|
371
|
+
* @property {Remote<StorageNode>} storageNode
|
|
372
|
+
* @property {StartedInstanceKit<SF> & { privateArgs?: Parameters<SF>[1] }} [kit]
|
|
373
|
+
* @property {Partial<Parameters<SF>[1]>} [initialPrivateArgs]
|
|
374
|
+
*/
|
|
375
|
+
|
|
376
|
+
/** @typedef {ReturnType<typeof prepareContractControl>} MakeContractControl */
|
|
377
|
+
|
|
378
|
+
// Hack to allow extracting the generic result of MakeContractControl
|
|
379
|
+
// See https://github.com/microsoft/TypeScript/issues/62524
|
|
380
|
+
|
|
381
|
+
const maker = /** @type {MakeContractControl} */ (
|
|
382
|
+
/** @type {unknown} */ (undefined)
|
|
383
|
+
);
|
|
384
|
+
harden(maker);
|
|
385
|
+
|
|
386
|
+
/** @template {ContractStartFunction} [SF=ContractStartFunction] @typedef {ReturnType<typeof maker<SF>>} ContractControl */
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/** @file core eval to deliver control of a contract to a smartWallet */
|
|
2
|
+
|
|
3
|
+
import { makeTracer } from '@agoric/internal/src/debug.js';
|
|
4
|
+
import { makeHeapZone } from '@agoric/zone';
|
|
5
|
+
import { Fail } from '@endo/errors';
|
|
6
|
+
import { E } from '@endo/eventual-send';
|
|
7
|
+
import { YMAX_CONTROL_WALLET_KEY } from '@agoric/portfolio-api/src/portfolio-constants.js';
|
|
8
|
+
import { prepareContractControl } from './contract-control.contract.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @import {ContractStartFunction} from '@agoric/zoe/src/zoeService/utils.js';
|
|
12
|
+
* @import {ChainStoragePresent} from './chain-info.core.js'
|
|
13
|
+
* @import {PostalServiceBoot} from './postal-service.core.js';
|
|
14
|
+
* @import {AttenuatedDepositPowers} from './attenuated-deposit.core.js';
|
|
15
|
+
* @import {ContractControlOpts, ContractControl, UpdatePrivateArgs} from './contract-control.contract.js';
|
|
16
|
+
* @import {PromiseSpaceOf} from '@agoric/vats/src/core/types.js';
|
|
17
|
+
* @import {BootstrapPowers} from '@agoric/vats/src/core/types.js';
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @template {ContractStartFunction} SF
|
|
22
|
+
* @typedef {Omit<ContractControlOpts<SF>, 'storageNode'> & {controlAddress: string}} ContractControlDeliverOpts
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {<SF extends ContractStartFunction>(opts: ContractControlDeliverOpts<SF>) => Promise<{delivered: Promise<void>, contractControl: ContractControl<SF>}>} DeliverContractControl
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {PromiseSpaceOf<{ deliverContractControl: DeliverContractControl}>} ContractControlPowers
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {BootstrapPowers &
|
|
35
|
+
* ChainStoragePresent &
|
|
36
|
+
* PostalServiceBoot &
|
|
37
|
+
* ContractControlPowers &
|
|
38
|
+
* AttenuatedDepositPowers
|
|
39
|
+
* } permitted
|
|
40
|
+
*/
|
|
41
|
+
export const produceDeliverContractControl = async permitted => {
|
|
42
|
+
permitted.produce.deliverContractControl.reset();
|
|
43
|
+
await null;
|
|
44
|
+
|
|
45
|
+
const { consume } = permitted;
|
|
46
|
+
|
|
47
|
+
const { chainStorage, getDepositFacet, zoe } = consume;
|
|
48
|
+
|
|
49
|
+
const instancePrivateArgs = await consume.instancePrivateArgs;
|
|
50
|
+
|
|
51
|
+
const postalSvcPub = E.when(
|
|
52
|
+
permitted.instance.consume.postalService,
|
|
53
|
+
instance => E(zoe).getPublicFacet(instance),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
/** @type {UpdatePrivateArgs} */
|
|
57
|
+
const updatePrivateArgs = (instance, privateArgs) => {
|
|
58
|
+
if (!instancePrivateArgs.has(instance)) {
|
|
59
|
+
Fail`instance doesn't have privateArgs`;
|
|
60
|
+
}
|
|
61
|
+
instancePrivateArgs.set(instance, privateArgs);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Use a heap zone to avoid entanglement with old liveslots
|
|
65
|
+
const zone = makeHeapZone();
|
|
66
|
+
const makeContractControl = prepareContractControl(zone, {
|
|
67
|
+
agoricNamesAdmin: await consume.agoricNamesAdmin,
|
|
68
|
+
board: await consume.board,
|
|
69
|
+
startUpgradable: await consume.startUpgradable,
|
|
70
|
+
updatePrivateArgs,
|
|
71
|
+
zoe: await zoe,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
/** @type {DeliverContractControl} */
|
|
75
|
+
const deliverContractControl = async ({
|
|
76
|
+
name: contractName,
|
|
77
|
+
controlAddress,
|
|
78
|
+
...opts
|
|
79
|
+
}) => {
|
|
80
|
+
await null;
|
|
81
|
+
|
|
82
|
+
const trace = makeTracer(`CCtrlCore-${contractName}`);
|
|
83
|
+
|
|
84
|
+
trace('creating contract control and delivering to', controlAddress);
|
|
85
|
+
|
|
86
|
+
const contractControl = makeContractControl({
|
|
87
|
+
name: contractName,
|
|
88
|
+
storageNode: await E(chainStorage).makeChildNode(contractName),
|
|
89
|
+
...opts,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
trace('reserving', controlAddress);
|
|
93
|
+
// This can block if the wallet is not provisioned
|
|
94
|
+
await E(getDepositFacet)(controlAddress);
|
|
95
|
+
|
|
96
|
+
trace(`delivering control`, controlAddress, contractControl);
|
|
97
|
+
// don't block on the recipient's offer
|
|
98
|
+
const delivered = E.when(
|
|
99
|
+
E(postalSvcPub).deliverPrize(
|
|
100
|
+
controlAddress,
|
|
101
|
+
contractControl,
|
|
102
|
+
YMAX_CONTROL_WALLET_KEY,
|
|
103
|
+
),
|
|
104
|
+
() => trace('control received'),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return harden({ delivered, contractControl });
|
|
108
|
+
};
|
|
109
|
+
harden(deliverContractControl);
|
|
110
|
+
|
|
111
|
+
permitted.produce.deliverContractControl.resolve(deliverContractControl);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const getManifestForDeliverContractControl = () => ({
|
|
115
|
+
manifest: {
|
|
116
|
+
[produceDeliverContractControl.name]: {
|
|
117
|
+
consume: {
|
|
118
|
+
agoricNamesAdmin: true,
|
|
119
|
+
board: true,
|
|
120
|
+
chainStorage: true,
|
|
121
|
+
getDepositFacet: true,
|
|
122
|
+
instancePrivateArgs: true,
|
|
123
|
+
startUpgradable: true,
|
|
124
|
+
zoe: true,
|
|
125
|
+
},
|
|
126
|
+
produce: {
|
|
127
|
+
deliverContractControl: true,
|
|
128
|
+
},
|
|
129
|
+
instance: {
|
|
130
|
+
consume: { postalService: true },
|
|
131
|
+
// provide: true,
|
|
132
|
+
},
|
|
133
|
+
installation: {
|
|
134
|
+
// provide: true,
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { CoreEvalBuilder, DeployScriptFunction } from '@agoric/deploy-script-support/src/externalTypes.js';
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { makeHelpers } from '../helpers.js';
|
|
6
|
+
import { getManifestForGetUpgradeKit } from './get-upgrade-kit.core.js';
|
|
7
|
+
|
|
8
|
+
const sourceSpec =
|
|
9
|
+
'@agoric/deploy-script-support/src/control/get-upgrade-kit.core.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @satisfies {CoreEvalBuilder}
|
|
13
|
+
*/
|
|
14
|
+
const defaultProposalBuilder = async () => {
|
|
15
|
+
return harden({
|
|
16
|
+
sourceSpec,
|
|
17
|
+
getManifestCall: [getManifestForGetUpgradeKit.name],
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** @type {DeployScriptFunction} */
|
|
22
|
+
const build = async (homeP, endowments) => {
|
|
23
|
+
const { writeCoreEval } = await makeHelpers(homeP, endowments);
|
|
24
|
+
|
|
25
|
+
await writeCoreEval('eval-get-upgrade-kit', () => defaultProposalBuilder());
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default build;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Get a contract upgrade kit by name.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { E } from '@endo/eventual-send';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @import {ContractStartFunction, Instance} from '@agoric/zoe/src/zoeService/utils.js';
|
|
9
|
+
* @import {StartedInstanceKit, StartedInstanceKitWithLabel} from '@agoric/vats/src/core/types.js';
|
|
10
|
+
* @import {PromiseSpaceOf} from '@agoric/vats/src/core/types.js';
|
|
11
|
+
* @import {BootstrapPowers} from '@agoric/vats/src/core/types.js';
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const trace = (...args) => console.log('---- GetUpgradeKit', ...args);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Similar to StartedInstanceKit, but with label and optional privateArgs
|
|
18
|
+
* managed by ContractControl.
|
|
19
|
+
*
|
|
20
|
+
* @template {ContractStartFunction} SF
|
|
21
|
+
* @typedef {StartedInstanceKit<SF> & {
|
|
22
|
+
* label: string;
|
|
23
|
+
* privateArgs?: Parameters<SF>[1];
|
|
24
|
+
* }} UpgradeKit
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* `getUpgradeKit` is a power allowing to retrieve a contract upgrade kit by
|
|
29
|
+
* the contract's name, without giving full access to the underlying stores.
|
|
30
|
+
*
|
|
31
|
+
* @typedef {PromiseSpaceOf<{
|
|
32
|
+
* getUpgradeKit: <SF extends ContractStartFunction>(name: string) => Promise<StartedInstanceKitWithLabel<SF>>
|
|
33
|
+
* }>} GetUpgradeKitPowers
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {BootstrapPowers & GetUpgradeKitPowers} powers
|
|
38
|
+
*/
|
|
39
|
+
export const produceGetUpgradeKit = async powers => {
|
|
40
|
+
powers.produce.getUpgradeKit.reset();
|
|
41
|
+
const { consume } = powers;
|
|
42
|
+
|
|
43
|
+
const agoricNames = await consume.agoricNames;
|
|
44
|
+
const contractKits = await consume.contractKits;
|
|
45
|
+
const instancePrivateArgs = await consume.instancePrivateArgs;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @template {ContractStartFunction} SF
|
|
49
|
+
* @param {string} name
|
|
50
|
+
* @returns {Promise<StartedInstanceKitWithLabel<SF>>}
|
|
51
|
+
*/
|
|
52
|
+
const getUpgradeKit = async name => {
|
|
53
|
+
trace('getting instance for', name);
|
|
54
|
+
/** @type {Instance<SF>} */
|
|
55
|
+
const instance = await E(agoricNames).lookup('instance', name);
|
|
56
|
+
|
|
57
|
+
trace('getting contract kit for', name);
|
|
58
|
+
const kit = /** @type {UpgradeKit<SF>} */ (contractKits.get(instance));
|
|
59
|
+
|
|
60
|
+
trace('getting privateArgs for', name);
|
|
61
|
+
const privateArgs = instancePrivateArgs.has(instance)
|
|
62
|
+
? /** @type {Parameters<SF>[1]} */ (instancePrivateArgs.get(instance))
|
|
63
|
+
: undefined;
|
|
64
|
+
|
|
65
|
+
return { ...kit, privateArgs };
|
|
66
|
+
};
|
|
67
|
+
harden(getUpgradeKit);
|
|
68
|
+
|
|
69
|
+
powers.produce.getUpgradeKit.resolve(getUpgradeKit);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export const getManifestForGetUpgradeKit = () => ({
|
|
73
|
+
manifest: {
|
|
74
|
+
[produceGetUpgradeKit.name]: {
|
|
75
|
+
consume: {
|
|
76
|
+
agoricNames: true,
|
|
77
|
+
contractKits: true,
|
|
78
|
+
instancePrivateArgs: true,
|
|
79
|
+
},
|
|
80
|
+
produce: { getUpgradeKit: true },
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { E } from '@endo/eventual-send';
|
|
2
|
+
import { passStyleOf } from '@endo/pass-style';
|
|
3
|
+
import { objectMap } from '@endo/patterns';
|
|
4
|
+
import { makeTracer } from '@agoric/internal/src/debug.js';
|
|
5
|
+
|
|
6
|
+
const contractName = 'postalService';
|
|
7
|
+
|
|
8
|
+
const trace = makeTracer('CCtrlCore');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @import {Installation} from '@agoric/zoe';
|
|
12
|
+
* @import {Instance} from '@agoric/zoe';
|
|
13
|
+
* @import {PromiseSpaceOf} from '@agoric/vats/src/core/types.js';
|
|
14
|
+
* @import {BootstrapPowers} from '@agoric/vats/src/core/types.js';
|
|
15
|
+
* @import {start} from '@aglocal/portfolio-deploy/src/control/postal-service.contract.js';
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {typeof start} PostalServiceStartFn
|
|
19
|
+
*
|
|
20
|
+
* @typedef {{
|
|
21
|
+
* installation: PromiseSpaceOf<{ postalService: Installation<PostalServiceStartFn>}>;
|
|
22
|
+
* instance: PromiseSpaceOf<{ postalService: Instance<PostalServiceStartFn>}>;
|
|
23
|
+
* }} PostalServiceBoot
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** @param {BootstrapPowers & PostalServiceBoot} permitted */
|
|
27
|
+
export const deployPostalService = async permitted => {
|
|
28
|
+
permitted.instance.produce.postalService.reset();
|
|
29
|
+
const { startUpgradable, namesByAddress } = permitted.consume;
|
|
30
|
+
const { postalService: installationP } = permitted.installation.consume;
|
|
31
|
+
trace('await: installation.postalService');
|
|
32
|
+
const installation = await installationP;
|
|
33
|
+
trace('await: namesByAddress');
|
|
34
|
+
const privateArgs = harden({
|
|
35
|
+
namesByAddress: await namesByAddress,
|
|
36
|
+
});
|
|
37
|
+
trace('await: startUpgradable(...)');
|
|
38
|
+
const kit = await E(startUpgradable)({
|
|
39
|
+
label: contractName,
|
|
40
|
+
installation,
|
|
41
|
+
privateArgs,
|
|
42
|
+
});
|
|
43
|
+
trace('kit', objectMap(kit, passStyleOf));
|
|
44
|
+
permitted.instance.produce.postalService.resolve(kit.instance);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const getManifestForPostalService = (
|
|
48
|
+
{ restoreRef },
|
|
49
|
+
{ installKeys },
|
|
50
|
+
) => ({
|
|
51
|
+
manifest: {
|
|
52
|
+
[deployPostalService.name]: {
|
|
53
|
+
consume: { startUpgradable: true, namesByAddress: true },
|
|
54
|
+
installation: { consume: { postalService: true } },
|
|
55
|
+
instance: { produce: { postalService: true } },
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
installations: { postalService: restoreRef(installKeys.postalService) },
|
|
59
|
+
});
|