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

Use (mostly numeric) vatID/deviceID everywhere within kernel #157

Merged
merged 1 commit into from
Sep 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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