-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(swingset): allow object refs in create/upgrade/terminate vat
This allows `E(vatAdminService).createVat(bundleID, { vatParameters })` to include object references in `vatParameters`, which are then delivered through the `dispatch.startVat()` delivery and made available to `buildRootObject(vatPowers, vatParameters)`. From within a vat, `vatPowers.exitVat(completion)` and `.exitVatWithFailure(reason)` can include object references, and they will be delivered to the parent caller's `done` promise. From outside the vat, `E(adminNode).terminateWithFailure(reason)` can take object refs in `reason` and they will be delivered to the parent caller's `done` promise. `E(adminNode).upgrade(bundleID, vatParameters)` can take object refs in `vatParameters` just like `createVat` (although `upgrade` itself is still non-functional). The kernel will maintain a refcount on each object passed through this mechanism, to keep it from being collected while in transit. This is implemented with the new "kernel device hooks" feature, which allows a device to call into the kernel and have its drefs translated into krefs. This will help with ZCF/contract vat upgrade, to pass the new contract bundlecap into the new ZCF vat via vatParameters. closes #4588 closes #4381 refs #1848
- Loading branch information
Showing
10 changed files
with
416 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { assert } from '@agoric/assert'; | ||
import { stringify, parse } from '@endo/marshal'; | ||
import { insistVatID } from '../lib/id.js'; | ||
|
||
export function makeVatAdminHooks(tools) { | ||
const { kernelKeeper, terminateVat } = tools; | ||
return { | ||
createByBundle(argsCapData) { | ||
// first, split off vatParameters | ||
const argsJSON = JSON.parse(argsCapData.body); | ||
const [bundle, { vatParameters: vpJSON, ...dynamicOptionsJSON }] = | ||
argsJSON; | ||
// assemble the vatParameters capdata | ||
const vatParameters = { | ||
body: JSON.stringify(vpJSON), | ||
slots: argsCapData.slots, | ||
}; | ||
// then re-parse the rest with marshal | ||
const dynamicOptions = parse(JSON.stringify(dynamicOptionsJSON)); | ||
// incref slots while create-vat is on run-queue | ||
for (const kref of vatParameters.slots) { | ||
kernelKeeper.incrementRefCount(kref, 'create-vat-event'); | ||
} | ||
const source = { bundle }; | ||
const vatID = kernelKeeper.allocateUnusedVatID(); | ||
const event = { | ||
type: 'create-vat', | ||
vatID, | ||
source, | ||
vatParameters, | ||
dynamicOptions, | ||
}; | ||
kernelKeeper.addToAcceptanceQueue(harden(event)); | ||
// the device gets the new vatID immediately, and will be notified | ||
// later when it is created and a root object is available | ||
const vatIDCapData = { body: JSON.stringify(vatID), slots: [] }; | ||
return harden(vatIDCapData); | ||
}, | ||
|
||
createByID(argsCapData) { | ||
// argsCapData is marshal([bundleID, options]), and options is { | ||
// vatParameters, ...rest }, and 'rest' is JSON-serializable (no | ||
// slots or bigints or undefined). We get the intermediate marshal | ||
// representation (with @qclass nodes), carve off vatParameters, | ||
// then reassemble the rest. All slots will be associated with | ||
// vatParameters. | ||
|
||
// first, split off vatParameters | ||
const argsJSON = JSON.parse(argsCapData.body); | ||
const [bundleID, { vatParameters: vpJSON, ...dynamicOptionsJSON }] = | ||
argsJSON; | ||
assert(kernelKeeper.hasBundle(bundleID), bundleID); | ||
// assemble the vatParameters capdata | ||
const vatParameters = { | ||
body: JSON.stringify(vpJSON), | ||
slots: argsCapData.slots, | ||
}; | ||
// then re-parse the rest with marshal | ||
const dynamicOptions = parse(JSON.stringify(dynamicOptionsJSON)); | ||
// incref slots while create-vat is on run-queue | ||
for (const kref of vatParameters.slots) { | ||
kernelKeeper.incrementRefCount(kref, 'create-vat-event'); | ||
} | ||
const source = { bundleID }; | ||
const vatID = kernelKeeper.allocateUnusedVatID(); | ||
const event = { | ||
type: 'create-vat', | ||
vatID, | ||
source, | ||
vatParameters, | ||
dynamicOptions, | ||
}; | ||
kernelKeeper.addToAcceptanceQueue(harden(event)); | ||
// the device gets the new vatID immediately, and will be notified | ||
// later when it is created and a root object is available | ||
const vatIDCapData = { body: JSON.stringify(vatID), slots: [] }; | ||
return harden(vatIDCapData); | ||
}, | ||
|
||
upgrade(argsCapData) { | ||
// marshal([bundleID, vatParameters]) -> upgradeID | ||
const argsJSON = JSON.parse(argsCapData.body); | ||
const [bundleID, vpJSON] = argsJSON; | ||
assert.typeof(bundleID, 'string'); | ||
const vpCD = { body: JSON.stringify(vpJSON), slots: argsCapData.slots }; | ||
for (const kref of vpCD.slots) { | ||
kernelKeeper.incrementRefCount(kref, 'upgrade-vat-event'); | ||
} | ||
const upgradeID = kernelKeeper.allocateUpgradeID(); | ||
const ev = { | ||
type: 'upgrade-vat', | ||
upgradeID, | ||
bundleID, | ||
vatParameters: vpCD, | ||
}; | ||
kernelKeeper.addToAcceptanceQueue(harden(ev)); | ||
const upgradeIDCD = { body: JSON.stringify(upgradeID), slots: [] }; | ||
return harden(upgradeIDCD); | ||
}, | ||
|
||
terminate(argsCD) { | ||
// marshal([vatID, reason]) -> null | ||
const argsJSON = JSON.parse(argsCD.body); | ||
const [vatID, reasonJSON] = argsJSON; | ||
insistVatID(vatID); | ||
const reasonCD = { ...argsCD, body: JSON.stringify(reasonJSON) }; | ||
// we don't need to incrementRefCount because if terminateVat sends | ||
// 'reason' to vat-admin, it uses notifyTermination / queueToKref / | ||
// doSend, and doSend() does its own incref | ||
terminateVat(vatID, true, reasonCD); | ||
return harden({ body: stringify(undefined), slots: [] }); | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.