Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

Commit

Permalink
Use (mostly numeric) vatID/deviceID everywhere within kernel
Browse files Browse the repository at this point in the history
.. as the index for kernel state data structures, instead of user-provided
vatName/deviceName strings. This will make it easier to use key/value state
storage (#144), since the keys will be more uniform (and shorter, and not
vulnerable to people using the separator string in their vat name). They look
like "vNN" and "dNN", where NN is a positive integer.

This will also make adding dynamic Vats easier (#19), as we'll just increment
a counter instead of asking the user to invent a unique name.

closes #146
  • Loading branch information
warner committed Sep 19, 2019
1 parent f942a79 commit 75e0b5c
Show file tree
Hide file tree
Showing 10 changed files with 587 additions and 394 deletions.
82 changes: 45 additions & 37 deletions src/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import makeDefaultEvaluateOptions from '@agoric/default-evaluate-options';
import kernelSourceFunc from './bundles/kernel';
import buildKernelNonSES from './kernel/index';
import bundleSource from './build-source-bundle';
import { insist } from './insist';
import { insistCapData } from './capdata';
import { parseVatSlot } from './parseVatSlots';

const evaluateOptions = makeDefaultEvaluateOptions();

Expand Down Expand Up @@ -133,8 +135,8 @@ export async function buildVatController(config, withSES = true, argv = []) {
: buildNonSESKernel(initialState);
// console.log('kernel', kernel);

async function addGenesisVat(vatID, sourceIndex, options = {}) {
console.log(`= adding vat '${vatID}' from ${sourceIndex}`);
async function addGenesisVat(name, sourceIndex, options = {}) {
console.log(`= adding vat '${name}' from ${sourceIndex}`);
if (!(sourceIndex[0] === '.' || path.isAbsolute(sourceIndex))) {
throw Error(
'sourceIndex must be relative (./foo) or absolute (/foo) not bare (foo)',
Expand Down Expand Up @@ -163,7 +165,7 @@ export async function buildVatController(config, withSES = true, argv = []) {
// eslint-disable-next-line global-require,import/no-dynamic-require
setup = require(`${sourceIndex}`).default;
}
kernel.addGenesisVat(vatID, setup, options);
kernel.addGenesisVat(name, setup, options);
}

async function addGenesisDevice(name, sourceIndex, endowments) {
Expand All @@ -185,13 +187,35 @@ export async function buildVatController(config, withSES = true, argv = []) {
kernel.addGenesisDevice(name, setup, endowments);
}

if (config.devices) {
for (const [name, srcpath, endowments] of config.devices) {
// eslint-disable-next-line no-await-in-loop
await addGenesisDevice(name, srcpath, endowments);
}
}

if (config.vats) {
for (const name of config.vats.keys()) {
const v = config.vats.get(name);
// eslint-disable-next-line no-await-in-loop
await addGenesisVat(name, v.sourcepath, v.options || {});
}
}

let bootstrapVatName;
if (config.bootstrapIndexJS) {
bootstrapVatName = '_bootstrap';
await addGenesisVat(bootstrapVatName, config.bootstrapIndexJS, {});
}

// start() may queue bootstrap if state doesn't say we did it already. It
// also replays the transcripts from a previous run, if any, which will
// execute vat code (but all syscalls will be disabled)
await kernel.start(bootstrapVatName, JSON.stringify(argv));

// the kernel won't leak our objects into the Vats, we must do
// the same in this wrapper
const controller = harden({
addVat(vatID, sourceIndex, options = {}) {
return addGenesisVat(vatID, sourceIndex, options);
},

log(str) {
kernel.log(str);
},
Expand All @@ -212,40 +236,24 @@ export async function buildVatController(config, withSES = true, argv = []) {
await kernel.step();
},

queueToExport(vatID, facetID, method, args) {
insistCapData(args);
kernel.addExport(vatID, facetID);
kernel.queueToExport(vatID, facetID, method, args);
// these are for tests

vatNameToID(vatName) {
return kernel.vatNameToID(vatName);
},
deviceNameToID(deviceName) {
return kernel.deviceNameToID(deviceName);
},

callBootstrap(vatID, bootstrapArgv) {
kernel.callBootstrap(`${vatID}`, JSON.stringify(bootstrapArgv));
queueToVatExport(vatName, exportID, method, args) {
const vatID = kernel.vatNameToID(vatName);
parseVatSlot(exportID);
insist(method === `${method}`);
insistCapData(args);
kernel.addExport(vatID, exportID);
kernel.queueToExport(vatID, exportID, method, args);
},
});

if (config.devices) {
for (const [name, srcpath, endowments] of config.devices) {
// eslint-disable-next-line no-await-in-loop
await addGenesisDevice(name, srcpath, endowments);
}
}

if (config.vats) {
for (const vatID of config.vats.keys()) {
const v = config.vats.get(vatID);
// eslint-disable-next-line no-await-in-loop
await addGenesisVat(vatID, v.sourcepath, v.options || {});
}
}

if (config.bootstrapIndexJS) {
await addGenesisVat('_bootstrap', config.bootstrapIndexJS, {});
}

// start() may queue bootstrap if state doesn't say we did it already. It
// also replays the transcripts from a previous run, if any, which will
// execute vat code (but all syscalls will be disabled)
await kernel.start('_bootstrap', JSON.stringify(argv));

return controller;
}
67 changes: 67 additions & 0 deletions src/kernel/id.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import harden from '@agoric/harden';
import Nat from '@agoric/nat';

// Vats are identified by an integer index, which (for typechecking purposes)
// is encoded as `vNN`. Devices are similarly identified as `dNN`. Both have
// human-readable names, which are provided to controller.addGenesisVat(),
// and usually come from the `vat-NAME.js` filenames processed in
// loadBasedir(). These names also appear in the `vats` and `devices`
// arguments to the bootstrap Vat's `bootstrap()` function, and in debug
// messages.

export function insistVatID(s) {
try {
if (s !== `${s}`) {
throw new Error(`not a string`);
}
s = `${s}`;
if (!s.startsWith(`v`)) {
throw new Error(`does not start with 'v'`);
}
Nat(Number(s.slice(1)));
} catch (e) {
throw new Error(`'${s} is not a 'vNN'-style VatID: ${e.message}`);
}
}

export function makeVatID(index) {
return `v${Nat(index)}`;
}

export function insistDeviceID(s) {
try {
if (s !== `${s}`) {
throw new Error(`not a string`);
}
s = `${s}`;
if (!s.startsWith(`d`)) {
throw new Error(`does not start with 'd'`);
}
Nat(Number(s.slice(1)));
} catch (e) {
throw new Error(`'${s} is not a 'dNN'-style DeviceID: ${e.message}`);
}
}

export function makeDeviceID(index) {
return `d${Nat(index)}`;
}

export function parseVatOrDeviceID(s) {
if (s !== `${s}`) {
throw new Error(`${s} is not a string, so cannot be a VatID/DevieID`);
}
s = `${s}`;
let type;
let idSuffix;
if (s.startsWith('v')) {
type = 'vat';
idSuffix = s.slice(1);
} else if (s.startsWith('v')) {
type = 'device';
idSuffix = s.slice(1);
} else {
throw new Error(`'${s}' is neither a VatID nor a DeviceID`);
}
return harden({ type, id: Nat(Number(idSuffix)) });
}
Loading

0 comments on commit 75e0b5c

Please sign in to comment.