Skip to content

Commit

Permalink
fix(swingset): add dummy dispatch.dropExports to liveslots/comms/mana…
Browse files Browse the repository at this point in the history
…gers

The new `dropExports()` doesn't do anything yet, but at least test that it
can be called directly in liveslots and comms. It should be reachable through
all vat worker types, but I won't be able to test that until we have a kernel
mechanism to provoke it.

closes #2653
  • Loading branch information
warner committed Mar 22, 2021
1 parent 1e4faa9 commit 5108ad6
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 12 deletions.
1 change: 1 addition & 0 deletions packages/SwingSet/docs/vat-worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ The `Delivery` object is a hardened Array of data (Objects, Arrays, and Strings,

* `['message', targetSlot, msg]`
* `['notify', resolutions]`
* `['dropExports', vrefs]`

In the `message` form, `targetSlot` is a object/promise reference (a string like `o+13` or `p-24`), which identifies the object or promise to which the message is being sent. This target can be a promise if the message is being pipelined to the result of some earlier message.

Expand Down
9 changes: 8 additions & 1 deletion packages/SwingSet/src/kernel/liveSlots.js
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,13 @@ function build(
}
}

function dropExports(vrefs) {
assert(Array.isArray(vrefs));
vrefs.map(vref => insistVatType('object', vref));
vrefs.map(vref => assert(parseVatSlot(vref).allocatedByVat));
console.log(`-- liveslots ignoring dropExports`);
}

// TODO: when we add notifyForward, guard against cycles

function exitVat(completion) {
Expand Down Expand Up @@ -676,7 +683,7 @@ function build(
slotToVal.set(rootSlot, rootObject);
}

const dispatch = harden({ deliver, notify });
const dispatch = harden({ deliver, notify, dropExports });
return harden({ vatGlobals, setBuildRootObject, dispatch, m });
}

Expand Down
7 changes: 7 additions & 0 deletions packages/SwingSet/src/kernel/vatManager/deliver.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ export function makeDeliver(tools, dispatch) {
return doProcess(['notify', resolutions], errmsg);
}

async function deliverOneDropExports(vrefs) {
const errmsg = `vat[${vatID}].dropExports failed`;
return doProcess(['dropExports', vrefs], errmsg);
}

// vatDeliverObject is:
// ['message', target, msg]
// target is vid
Expand All @@ -109,6 +114,8 @@ export function makeDeliver(tools, dispatch) {
return deliverOneMessage(...args);
case 'notify':
return deliverOneNotification(...args);
case 'dropExports':
return deliverOneDropExports(...args);
default:
assert.fail(X`unknown delivery type ${type}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ function doNotify(resolutions) {
return doProcess(['notify', resolutions], errmsg);
}

function doDropExports(vrefs) {
const errmsg = `vat.doDropExport failed`;
return doProcess(['dropExports', vrefs], errmsg);
}

parentPort.on('message', ([type, ...margs]) => {
workerLog(`received`, type);
if (type === 'start') {
Expand Down Expand Up @@ -143,6 +148,8 @@ parentPort.on('message', ([type, ...margs]) => {
doMessage(...dargs).then(res => sendUplink(['deliverDone', ...res]));
} else if (dtype === 'notify') {
doNotify(...dargs).then(res => sendUplink(['deliverDone', ...res]));
} else if (dtype === 'dropExports') {
doDropExports(...dargs).then(res => sendUplink(['deliverDone', ...res]));
} else {
assert.fail(X`bad delivery type ${dtype}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ function doNotify(resolutions) {
return doProcess(['notify', resolutions], errmsg);
}

function doDropExports(vrefs) {
const errmsg = `vat.doDropExport failed`;
return doProcess(['dropExports', vrefs], errmsg);
}

const toParent = arrayEncoderStream();
toParent
.pipe(netstringEncoderStream())
Expand Down Expand Up @@ -163,6 +168,8 @@ fromParent.on('data', ([type, ...margs]) => {
doMessage(...dargs).then(res => sendUplink(['deliverDone', ...res]));
} else if (dtype === 'notify') {
doNotify(...dargs).then(res => sendUplink(['deliverDone', ...res]));
} else if (dtype === 'dropExports') {
doDropExports(...dargs).then(res => sendUplink(['deliverDone', ...res]));
} else {
assert.fail(X`bad delivery type ${dtype}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ function makeWorker(port) {
return doProcess(['notify', resolutions], errmsg);
}

/** @type { (rs: unknown) => Promise<Tagged> } */
function doDropExports(vrefs) {
const errmsg = `vat.dropExports failed`;
return doProcess(['dropExports', vrefs], errmsg);
}

/**
* TODO: consider other methods per SES VirtualConsole.
* See https://github.com/Agoric/agoric-sdk/issues/2146
Expand Down Expand Up @@ -277,6 +283,8 @@ function makeWorker(port) {
return doMessage(dargs[0], dargs[1]);
case 'notify':
return doNotify(dargs[0]);
case 'dropExports':
return doDropExports(dargs[0]);
default:
assert.fail(X`bad delivery type ${dtype}`);
}
Expand Down
11 changes: 9 additions & 2 deletions packages/SwingSet/src/vats/comms/dispatch.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, details as X } from '@agoric/assert';
import { makeVatSlot } from '../../parseVatSlots';
import { makeVatSlot, insistVatType, parseVatSlot } from '../../parseVatSlots';
import { getRemote } from './remote';
import { makeState, makeStateKit } from './state';
import { deliverToController } from './controller';
Expand Down Expand Up @@ -109,7 +109,14 @@ export function buildCommsDispatch(
// comms vat version of it) here?
}

const dispatch = harden({ deliver, notify });
function dropExports(vrefs) {
assert(Array.isArray(vrefs));
vrefs.map(vref => insistVatType('object', vref));
vrefs.map(vref => assert(parseVatSlot(vref).allocatedByVat));
console.log(`-- comms ignoring dropExports`);
}

const dispatch = harden({ deliver, notify, dropExports });
debugState.set(dispatch, { state, clistKit });

return dispatch;
Expand Down
17 changes: 11 additions & 6 deletions packages/SwingSet/test/test-comms.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,19 @@ test('receive', t => {
encodeArgs(`deliver:${bobRemote}:bar::ro-20:${bobRemote};argsbytes`),
null,
);
const expectedAliceKernel = 'o+31';
t.deepEqual(sends.shift(), [
bobKernel,
'bar',
capdata('argsbytes', ['o+31', bobKernel]),
capdata('argsbytes', [expectedAliceKernel, bobKernel]),
]);
// if we were to send o+31/lo11, the other side should get ro+20, which is alice
t.is(getRemoteForLocal(remoteID, 'lo11'), 'ro+20');
t.is(getLocalForRemote(remoteID, 'ro-20'), 'lo11');
t.is(getKernelForLocal('lo11'), 'o+31');
t.is(getLocalForKernel('o+31'), 'lo11');
t.is(getKernelForLocal('lo11'), expectedAliceKernel);
t.is(getLocalForKernel(expectedAliceKernel), 'lo11');

// bob!bar(alice, bob)
// bob!bar(alice, bob), again, to test stability
d.deliver(
receiverID,
'receive',
Expand All @@ -176,10 +177,11 @@ test('receive', t => {
t.deepEqual(sends.shift(), [
bobKernel,
'bar',
capdata('argsbytes', ['o+31', bobKernel]),
capdata('argsbytes', [expectedAliceKernel, bobKernel]),
]);

// bob!cat(alice, bob, ayana)
const expectedAyanaKernel = 'o+32';
d.deliver(
receiverID,
'receive',
Expand All @@ -189,6 +191,9 @@ test('receive', t => {
t.deepEqual(sends.shift(), [
bobKernel,
'cat',
capdata('argsbytes', ['o+31', bobKernel, 'o+32']),
capdata('argsbytes', [expectedAliceKernel, bobKernel, expectedAyanaKernel]),
]);

// make sure comms can tolerate dropExports, even if it's a no-op
d.dropExports([expectedAliceKernel, expectedAyanaKernel]);
});
49 changes: 46 additions & 3 deletions packages/SwingSet/test/test-liveslots.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,17 @@ function capargs(args, slots = []) {
return capdata(JSON.stringify(args), slots);
}

function caponeslot(slot) {
return capargs([{ '@qclass': 'slot', index: 0 }], [slot]);
function capdataOneSlot(slot) {
return capargs({ '@qclass': 'slot', iface: 'Alleged: export', index: 0 }, [
slot,
]);
}

function capargsOneSlot(slot) {
return capargs(
[{ '@qclass': 'slot', iface: 'Alleged: export', index: 0 }],
[slot],
);
}

function oneResolution(promiseID, rejected, data) {
Expand Down Expand Up @@ -639,7 +648,7 @@ test('disavow', async t => {
const import1 = 'o-1';

// root~.one(import1) // sendOnly
dispatch.deliver(rootA, 'one', caponeslot(import1), undefined);
dispatch.deliver(rootA, 'one', capargsOneSlot(import1), undefined);
await waitUntilQuiescent();
t.deepEqual(log.shift(), { type: 'dropImports', slots: [import1] });
t.deepEqual(log.shift(), 'disavowed pres1');
Expand Down Expand Up @@ -672,3 +681,37 @@ test('disavow', async t => {
t.deepEqual(log.shift(), 'tried to send to disavowed');
t.deepEqual(log, []);
});

test('dropExports', async t => {
const { log, syscall } = buildSyscall();

function build(_vatPowers) {
const ex1 = Far('export', {});
const root = Far('root', {
one() {
return ex1;
},
});
return root;
}
const dispatch = makeDispatch(syscall, build, true);
t.deepEqual(log, []);
const rootA = 'o+0';

// rp1 = root~.one()
// ex1 = await rp1
const rp1 = 'p-1';
dispatch.deliver(rootA, 'one', capargs([]), rp1);
await waitUntilQuiescent();
const l1 = log.shift();
const ex1 = l1.resolutions[0][2].slots[0];
t.deepEqual(l1, {
type: 'resolve',
resolutions: [[rp1, false, capdataOneSlot(ex1)]],
});
t.deepEqual(log, []);

// now tell the vat to drop that export
dispatch.dropExports([ex1]);
// for now, all that we care about is that liveslots doesn't crash
});

0 comments on commit 5108ad6

Please sign in to comment.