Skip to content

Commit

Permalink
fix(spawner): rewrite to use createVat, strip down to bare minimum API
Browse files Browse the repository at this point in the history
This removes all zoe-like functionality from the spawner, leaving a bare
install() and spawn() API. This is now effectively a wrapper around
createVat(), except that it accepts source code which exports a default
function, rather than an export named `buildRootObject`, and it does not
return the control facet (`adminNode`) to the caller.

Our two cosmic-swingset applications (chain and ag-solo) are updated to
create the spawner correctly. Dapps can continue to use the existing API
without changes.

closes #1343
  • Loading branch information
warner committed Apr 23, 2021
1 parent 4887515 commit dc63140
Show file tree
Hide file tree
Showing 30 changed files with 253 additions and 1,985 deletions.
12 changes: 8 additions & 4 deletions packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export function buildRootObject(vatPowers, vatParameters) {
E(vats.board).getBoard(),
E(vats.timer).createTimerService(timerDevice),
/** @type {ERef<ZoeService>} */ (E(vats.zoe).buildZoe(vatAdminSvc)),
E(vats.host).makeHost(),
E(vats.spawner).buildSpawner(vatAdminSvc),
E(vats.priceAuthority).makePriceAuthority(),
]);

Expand Down Expand Up @@ -602,10 +602,10 @@ export function buildRootObject(vatPowers, vatParameters) {
// objects that live in the client's solo vat. Some services should only
// be in the DApp environment (or only in end-user), but we're not yet
// making a distinction, so the user also gets them.
async function createLocalBundle(vats, devices) {
async function createLocalBundle(vats, devices, vatAdminSvc) {
// This will eventually be a vat spawning service. Only needed by dev
// environments.
const spawner = E(vats.host).makeHost();
const spawner = E(vats.spawner).buildSpawner(vatAdminSvc);

// Needed for DApps, maybe for user clients.
const uploads = E(vats.uploads).getUploads();
Expand Down Expand Up @@ -725,7 +725,11 @@ export function buildRootObject(vatPowers, vatParameters) {
GCI,
PROVISIONER_INDEX,
);
const localBundle = await createLocalBundle(vats, devices);
const localBundle = await createLocalBundle(
vats,
devices,
vatAdminSvc,
);
await E(vats.http).setPresences(localBundle);
const bundle = await E(demoProvider).getDemoBundle();
await E(vats.http).setPresences(localBundle, bundle, {
Expand Down
4 changes: 2 additions & 2 deletions packages/cosmic-swingset/lib/ag-solo/vats/chain-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"board": {
"sourceSpec": "vat-board.js"
},
"host": {
"sourceSpec": "vat-host.js"
"spawner": {
"sourceSpec": "vat-spawner.js"
},
"ibc": {
"sourceSpec": "vat-ibc.js"
Expand Down
4 changes: 2 additions & 2 deletions packages/cosmic-swingset/lib/ag-solo/vats/solo-config.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"bootstrap": "bootstrap",
"vats": {
"host": {
"sourceSpec": "vat-host.js"
"spawner": {
"sourceSpec": "vat-spawner.js"
},
"http": {
"sourceSpec": "vat-http.js"
Expand Down
12 changes: 0 additions & 12 deletions packages/cosmic-swingset/lib/ag-solo/vats/vat-host.js

This file was deleted.

13 changes: 13 additions & 0 deletions packages/cosmic-swingset/lib/ag-solo/vats/vat-spawner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (C) 2018 Agoric, under Apache License 2.0
import { Far } from '@agoric/marshal';
import { makeSpawner } from '@agoric/spawner';

function buildRootObject() {
return Far('root', {
buildSpawner(vatAdminSvc) {
return makeSpawner(vatAdminSvc);
},
});
}
harden(buildRootObject);
export { buildRootObject };
56 changes: 54 additions & 2 deletions packages/spawner/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,56 @@
# Spawner

The original contractHost, which will be turned into a general purpose
vat spawner now that we have Zoe for most smart contracts.
The "spawner" was the original method for instantiating contract code within
the chain's swingset. This on-chain usage has been entirely superceded by
Zoe, and the chain swingset no longer includes a spawner.

However, it was also pressed into service in the ag-solo swingset for
executing deploy scripts that need to leave code running after the script
finishes, such as an HTTP API handler. This use case is still active, but
none of the callers need the zoe-like features (comparable contract identity,
source retrieval, issuers, invitations, or seats). These callers now do
something like:

```js
const bundle = await bundleSource(pathResolve(__dirname, './src/wallet.js'));
const walletInstall = E(spawner).install(bundle);
const walletVat = await E(walletInstall).spawn(args);
```

So the spawner is now a stripped-down dynamic-vat creation frontend with the
minimal code necessary to satisfy those callers.

The spawner expects to be running in a vat. It used to evaluate the submitted
code in its own vat, under "within-vat" metering to protect itself from
runaway guest code. It has been rewritten to evaluate the guest in a new
dynamic vat instead.

To support a spawner, your swingset must provide it with the `vatAdmin` facet
(to create new vats), and a copy of the `vat-spawned.js` bundle (to install
in the new vat). Your `vat-spawner.js` should look like:

```js
import { Far } from '@agoric/marshal';
import { makeSpawner } from '@agoric/spawner';
function buildRootObject() {
return Far('root', {
buildSpawner(vatAdminSvc) {
return makeSpawner(vatAdminSvc);
}
});
}
harden(buildRootObject);
export { buildRootObject };
```

And your bootstrap function needs something like this:

```js
return Far('root', {
async bootstrap(vats, devices) {
const vatAdminSvc = await E(vats.vatAdmin).createVatAdminService(
devices.vatAdmin,
);
const spawner = await E(vats.spawner).buildSpawner(vatAdminSvc);
// ...
```
12 changes: 4 additions & 8 deletions packages/spawner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"node": ">=11.0"
},
"scripts": {
"build": "exit 0",
"build": "yarn build-bundle-spawn",
"build-bundle-spawn": "node -r esm scripts/build-bundle-spawn.js",
"test": "ava",
"test:nyc": "nyc ava",
"test:xs": "exit 0",
Expand All @@ -32,17 +33,12 @@
"homepage": "https://github.com/Agoric/agoric-sdk#readme",
"dependencies": {
"@agoric/assert": "^0.2.8",
"@agoric/ertp": "^0.10.7",
"@agoric/eventual-send": "^0.13.10",
"@agoric/import-bundle": "^0.2.10",
"@agoric/marshal": "^0.4.7",
"@agoric/nat": "^4.0.0",
"@agoric/promise-kit": "^0.2.9",
"@agoric/same-structure": "^0.1.9",
"@agoric/store": "^0.4.10",
"@agoric/transform-metering": "^1.4.8"
"@agoric/marshal": "^0.4.7"
},
"devDependencies": {
"@agoric/bundle-source": "^1.3.3",
"@agoric/install-metering-and-ses": "^0.2.9",
"@agoric/install-ses": "^0.5.9",
"@agoric/swingset-vat": "^0.16.3",
Expand Down
33 changes: 33 additions & 0 deletions packages/spawner/scripts/build-bundle-spawn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* global __dirname */

// eslint-disable-next-line import/no-extraneous-dependencies
import 'ses';
import fs from 'fs';
import process from 'process';
import bundleSource from '@agoric/bundle-source';

async function writeSourceBundle(contractFilename, outputPath) {
await bundleSource(contractFilename).then(bundle => {
// TODO: fix
// @ts-ignore mkdirSync believes it only accepts 2 arguments.
fs.mkdirSync(`${__dirname}/../bundles`, { recursive: true }, err => {
if (err) throw err;
});
fs.writeFileSync(outputPath, `export default ${JSON.stringify(bundle)};`);
});
}

async function main() {
const contractFilename = `${__dirname}/../src/vat-spawned.js`;
const outputPath = `${__dirname}/../bundles/bundle-spawn.js`;
await writeSourceBundle(contractFilename, outputPath);
}

main().then(
_ => process.exit(0),
err => {
console.log('error creating spawn bundle:');
console.log(err);
process.exit(1);
},
);
35 changes: 0 additions & 35 deletions packages/spawner/src/allSettled.js

This file was deleted.

Loading

0 comments on commit dc63140

Please sign in to comment.