Skip to content

Commit

Permalink
feat: make vatstore optionally available to vats as a vat power
Browse files Browse the repository at this point in the history
  • Loading branch information
FUDCo committed Jun 14, 2021
1 parent d991df7 commit 229da78
Show file tree
Hide file tree
Showing 19 changed files with 226 additions and 73 deletions.
1 change: 1 addition & 0 deletions packages/SwingSet/src/kernel/initializeKernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export function initializeKernel(config, hostStorage, verbose = false) {
'managerType',
'enableDisavow',
'enableSetup',
'enableVatstore',
'virtualObjectCacheSize',
'useTranscript',
]);
Expand Down
23 changes: 23 additions & 0 deletions packages/SwingSet/src/kernel/liveSlots.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const DEFAULT_VIRTUAL_OBJECT_CACHE_SIZE = 3; // XXX ridiculously small value to
* @param {*} forVatID Vat ID label, for use in debug diagostics
* @param {number} cacheSize Maximum number of entries in the virtual object state cache
* @param {boolean} enableDisavow
* @param {boolean} enableVatstore
* @param {*} vatPowers
* @param {*} vatParameters
* @param {*} gcTools { WeakRef, FinalizationRegistry, waitUntilQuiescent, gcAndFinalize }
Expand All @@ -40,6 +41,7 @@ function build(
forVatID,
cacheSize,
enableDisavow,
enableVatstore,
vatPowers,
vatParameters,
gcTools,
Expand Down Expand Up @@ -916,6 +918,23 @@ function build(
if (enableDisavow) {
vpow.disavow = disavow;
}
if (enableVatstore) {
vpow.vatstore = harden({
get: key => {
assert.typeof(key, 'string');
return syscall.vatstoreGet(`vvs.${key}`);
},
set: (key, value) => {
assert.typeof(key, 'string');
assert.typeof(value, 'string');
syscall.vatstoreSet(`vvs.${key}`, value);
},
delete: key => {
assert.typeof(key, 'string');
syscall.vatstoreDelete(`vvs.${key}`);
},
});
}

// here we finally invoke the vat code, and get back the root object
const rootObject = buildRootObject(harden(vpow), harden(vatParameters));
Expand Down Expand Up @@ -1029,6 +1048,7 @@ function build(
* @param {*} vatParameters
* @param {number} cacheSize Upper bound on virtual object cache size
* @param {boolean} enableDisavow
* @param {boolean} enableVatstore
* @param {*} gcTools { WeakRef, FinalizationRegistry, waitUntilQuiescent }
* @param {Console} [liveSlotsConsole]
* @returns {*} { vatGlobals, inescapableGlobalProperties, dispatch, setBuildRootObject }
Expand Down Expand Up @@ -1062,6 +1082,7 @@ export function makeLiveSlots(
vatParameters = harden({}),
cacheSize = DEFAULT_VIRTUAL_OBJECT_CACHE_SIZE,
enableDisavow = false,
enableVatstore = false,
gcTools,
liveSlotsConsole = console,
) {
Expand All @@ -1074,6 +1095,7 @@ export function makeLiveSlots(
forVatID,
cacheSize,
enableDisavow,
enableVatstore,
allVatPowers,
vatParameters,
gcTools,
Expand Down Expand Up @@ -1102,6 +1124,7 @@ export function makeMarshaller(syscall, gcTools) {
'forVatID',
DEFAULT_VIRTUAL_OBJECT_CACHE_SIZE,
false,
false,
{},
{},
gcTools,
Expand Down
8 changes: 8 additions & 0 deletions packages/SwingSet/src/kernel/loadVat.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export function makeVatLoader(stuff) {
'vatParameters',
'enableSetup',
'enablePipelining',
'enableVatstore',
'virtualObjectCacheSize',
'useTranscript',
];
Expand All @@ -96,6 +97,7 @@ export function makeVatLoader(stuff) {
'enableDisavow',
'enableSetup',
'enablePipelining',
'enableVatstore',
'virtualObjectCacheSize',
'useTranscript',
];
Expand Down Expand Up @@ -141,6 +143,10 @@ export function makeVatLoader(stuff) {
* without waiting for the promises to be resolved. If false, such
* messages will be queued inside the kernel. Defaults to false.
*
* 'enableVatstore' If true, the vat is provided with an object that allows
* individual keyed access (in an insolated subset of the key space) to
* the vatstore. Defaults to false.
*
* 'useTranscript' If true, saves a transcript of a vat's inbound
* deliveries and outbound syscalls so that the vat's internal state
* can be reconstructed via replay. If false, no such record is kept.
Expand Down Expand Up @@ -175,6 +181,7 @@ export function makeVatLoader(stuff) {
enableSetup = false,
enableDisavow = false,
enablePipelining = false,
enableVatstore = false,
virtualObjectCacheSize,
useTranscript = true,
name,
Expand Down Expand Up @@ -206,6 +213,7 @@ export function makeVatLoader(stuff) {
vatConsole: makeVatConsole('vat', vatID),
liveSlotsConsole: makeVatConsole('ls', vatID),
vatParameters,
enableVatstore,
virtualObjectCacheSize,
useTranscript,
name,
Expand Down
1 change: 1 addition & 0 deletions packages/SwingSet/src/kernel/vatManager/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export function makeVatManagerFactory({
'enableDisavow',
'enableSetup',
'liveSlotsConsole',
'enableVatstore',
'virtualObjectCacheSize',
'useTranscript',
'vatParameters',
Expand Down
2 changes: 2 additions & 0 deletions packages/SwingSet/src/kernel/vatManager/manager-local.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export function makeLocalVatManagerFactory(tools) {
vatParameters = {},
vatConsole,
liveSlotsConsole,
enableVatstore = false,
virtualObjectCacheSize,
compareSyscalls,
useTranscript,
Expand Down Expand Up @@ -139,6 +140,7 @@ export function makeLocalVatManagerFactory(tools) {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
gcTools,
liveSlotsConsole,
);
Expand Down
2 changes: 2 additions & 0 deletions packages/SwingSet/src/kernel/vatManager/manager-nodeworker.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function makeNodeWorkerVatManagerFactory(tools) {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
compareSyscalls,
useTranscript,
} = managerOptions;
Expand Down Expand Up @@ -114,6 +115,7 @@ export function makeNodeWorkerVatManagerFactory(tools) {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
]);

function deliverToWorker(delivery) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function makeNodeSubprocessFactory(tools) {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
compareSyscalls,
useTranscript,
} = managerOptions;
Expand Down Expand Up @@ -109,6 +110,7 @@ export function makeNodeSubprocessFactory(tools) {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
]);

function shutdown() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export function makeXsSubprocessFactory({
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
name,
metered,
compareSyscalls,
Expand Down Expand Up @@ -126,6 +127,7 @@ export function makeXsSubprocessFactory({
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
]);
if (bundleReply[0] === 'dispatchReady') {
parentLog(vatID, `bundle loaded. dispatch ready.`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ parentPort.on('message', ([type, ...margs]) => {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
] = margs;

function testLog(...args) {
Expand Down Expand Up @@ -89,6 +90,7 @@ parentPort.on('message', ([type, ...margs]) => {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
gcTools,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ fromParent.on('data', ([type, ...margs]) => {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
] = margs;

function testLog(...args) {
Expand Down Expand Up @@ -102,6 +103,7 @@ fromParent.on('data', ([type, ...margs]) => {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
gcTools,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ function makeWorker(port) {
* @param {unknown} vatParameters
* @param {unknown} virtualObjectCacheSize
* @param {boolean} enableDisavow
* @param {boolean} enableVatstore
* @returns { Promise<Tagged> }
*/
async function setBundle(
Expand All @@ -151,6 +152,7 @@ function makeWorker(port) {
vatParameters,
virtualObjectCacheSize,
enableDisavow,
enableVatstore,
) {
/** @type { (vso: VatSyscallObject) => VatSyscallResult } */
function syscallToManager(vatSyscallObject) {
Expand Down Expand Up @@ -195,6 +197,7 @@ function makeWorker(port) {
vatParameters,
cacheSize,
enableDisavow,
enableVatstore,
gcTools,
);

Expand Down Expand Up @@ -227,7 +230,15 @@ function makeWorker(port) {
case 'setBundle': {
assert(!dispatch, 'cannot setBundle again');
const enableDisavow = !!args[4];
return setBundle(args[0], args[1], args[2], args[3], enableDisavow);
const enableVatstore = !!args[5];
return setBundle(
args[0],
args[1],
args[2],
args[3],
enableDisavow,
enableVatstore,
);
}
case 'deliver': {
assert(dispatch, 'cannot deliver before setBundle');
Expand Down
6 changes: 3 additions & 3 deletions packages/SwingSet/src/kernel/virtualObjectManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export function makeVirtualObjectManager(
* @returns {*} an object representing the object's stored state.
*/
function fetch(vobjID) {
return JSON.parse(syscall.vatstoreGet(vobjID));
return JSON.parse(syscall.vatstoreGet(`vom.${vobjID}`));
}

/**
Expand All @@ -185,7 +185,7 @@ export function makeVirtualObjectManager(
* @param {*} rawData A data object representing the state to be written.
*/
function store(vobjID, rawData) {
syscall.vatstoreSet(vobjID, JSON.stringify(rawData));
syscall.vatstoreSet(`vom.${vobjID}`, JSON.stringify(rawData));
}

const cache = makeCache(cacheSize, fetch, store);
Expand Down Expand Up @@ -308,7 +308,7 @@ export function makeVirtualObjectManager(
if (vobjID) {
const { type, virtual, allocatedByVat } = parseVatSlot(vobjID);
if (type === 'object' && (virtual || !allocatedByVat)) {
return `ws${storeID}.${vobjID}`;
return `vom.ws${storeID}.${vobjID}`;
}
}
return undefined;
Expand Down
1 change: 1 addition & 0 deletions packages/SwingSet/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* metered?: boolean,
* enableDisavow?: boolean,
* useTranscript?: boolean,
* enableVatstore?: boolean,
* vatParameters: Record<string, unknown>,
* virtualObjectCacheSize: number,
* name: string,
Expand Down
1 change: 1 addition & 0 deletions packages/SwingSet/test/liveslots-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export function makeDispatch(
{},
undefined,
enableDisavow,
false,
gcTools,
);
setBuildRootObject(build);
Expand Down
11 changes: 10 additions & 1 deletion packages/SwingSet/test/test-liveslots.js
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,16 @@ test('dropImports', async t => {
return root;
}

const ls = makeLiveSlots(syscall, 'vatA', {}, {}, undefined, false, gcTools);
const ls = makeLiveSlots(
syscall,
'vatA',
{},
{},
undefined,
false,
false,
gcTools,
);
const { setBuildRootObject, dispatch, deadSet } = ls;
setBuildRootObject(build);
const allFRs = gcTools.getAllFRs();
Expand Down
60 changes: 60 additions & 0 deletions packages/SwingSet/test/test-vatstore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* global require */
// eslint-disable-next-line import/order
import { test } from '../tools/prepare-test-env-ava';

import { provideHostStorage } from '../src/hostStorage';
import { buildVatController } from '../src/index';
import { capargs } from './util.js';

test('vatstore', async t => {
const config = {
bootstrap: 'bootstrap',
vats: {
bootstrap: {
sourceSpec: require.resolve('./vat-vatstore.js'),
creationOptions: {
enableVatstore: true,
},
},
},
};
const hostStorage = provideHostStorage();
const c = await buildVatController(config, [], {
hostStorage,
});

function send(msg, ...args) {
c.queueToVatExport('bootstrap', 'o+0', msg, capargs(args));
}

send('get', 'zot');
await c.run();
send('store', 'zot', 'first zot');
send('get', 'zot');
send('get', 'foo');
send('store', 'zot', 'second zot');
send('store', 'foo', 'first foo');
send('get', 'zot');
send('delete', 'zot');
send('get', 'foo');
send('get', 'zot');
await c.run();

t.deepEqual(c.dump().log, [
'get zot -> <undefined>',
'store zot <- "first zot"',
'get zot -> "first zot"',
'get foo -> <undefined>',
'store zot <- "second zot"',
'store foo <- "first foo"',
'get zot -> "second zot"',
'delete zot',
'get foo -> "first foo"',
'get zot -> <undefined>',
]);
for (const k of hostStorage.kvStore.getKeys('', '')) {
if (k.endsWith('.foo')) {
t.is(k, 'v1.vs.vvs.foo');
}
}
});
Loading

0 comments on commit 229da78

Please sign in to comment.