Skip to content

Commit

Permalink
feat(zoe): implement metering of contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Feb 26, 2020
1 parent ce077a3 commit 9138801
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 15 deletions.
26 changes: 26 additions & 0 deletions packages/zoe/src/evalContractCode.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/* global replaceGlobalMeter */
import evaluate from '@agoric/evaluate';
import Nat from '@agoric/nat';
import harden from '@agoric/harden';

import { makeMeter } from '@agoric/transform-metering/src/meter';

import { makeMint } from '@agoric/ertp/src/mint';
import { assert, details } from '@agoric/assert';
import makePromise from '@agoric/make-promise';
Expand Down Expand Up @@ -31,6 +34,29 @@ const evalContractCode = (code, additionalEndowments) => {
...Object.getOwnPropertyDescriptors(defaultEndowments),
...Object.getOwnPropertyDescriptors(additionalEndowments),
});

// Refill a meter each time.
// NOTE: We need 1e7 or the autoswap contract exhausts
// the compute meter.
const { meter, refillFacet } = makeMeter({ budgetCombined: 1e7 });
const doRefill = () => {
if (meter.isExhausted()) {
// Don't refill.
return;
}
// Refill the meter, since we're leaving a crank.
Object.values(refillFacet, r => r());
};

// Make an endowment to get our meter.
fullEndowments.getGlobalMeter = m => {
if (m !== true && typeof replaceGlobalMeter !== 'undefined') {
// Replace the global meter and register our refiller.
replaceGlobalMeter(meter, doRefill);
}
return meter;
};

// Evaluate the export function, and use the resulting
// module namespace as our installation.

Expand Down
34 changes: 22 additions & 12 deletions packages/zoe/test/swingsetTests/zoe-metering/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,34 @@ import harden from '@agoric/harden';
import infiniteInstallLoopBundle from './bundle-infiniteInstallLoop';
import infiniteInstanceLoopBundle from './bundle-infiniteInstanceLoop';
import infiniteTestLoopBundle from './bundle-infiniteTestLoop';
import testBuiltinsBundle from './bundle-testBuiltins';

function build(E, log) {
const obj0 = {
async bootstrap(argv, vats) {
const zoe = await E(vats.zoe).getZoe();

const installations = {
infiniteInstallLoop: () => E(zoe).install(
infiniteInstallLoopBundle.source,
infiniteInstallLoopBundle.moduleFormat,
),
infiniteInstanceLoop: () => E(zoe).install(
infiniteInstanceLoopBundle.source,
infiniteInstanceLoopBundle.modelFormat,
),
infiniteTestLoop: () => E(zoe).install(
infiniteTestLoopBundle.source,
infiniteTestLoopBundle.moduleFormat,
),
infiniteInstallLoop: () =>
E(zoe).install(
infiniteInstallLoopBundle.source,
infiniteInstallLoopBundle.moduleFormat,
),
infiniteInstanceLoop: () =>
E(zoe).install(
infiniteInstanceLoopBundle.source,
infiniteInstanceLoopBundle.modelFormat,
),
infiniteTestLoop: () =>
E(zoe).install(
infiniteTestLoopBundle.source,
infiniteTestLoopBundle.moduleFormat,
),
testBuiltins: () =>
E(zoe).install(
testBuiltinsBundle.source,
testBuiltinsBundle.moduleFormat,
),
};

const [testName] = argv;
Expand All @@ -36,6 +45,7 @@ function build(E, log) {
const { publicAPI } = await E(zoe).getInstance(instanceHandle);
log(`invoking ${testName}.doTest()`);
await E(publicAPI).doTest();
log(`complete`);
},
};
return harden(obj0);
Expand Down
33 changes: 30 additions & 3 deletions packages/zoe/test/swingsetTests/zoe-metering/test-zoe-metering.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const CONTRACT_FILES = [
'infiniteInstallLoop',
'infiniteInstanceLoop',
'infiniteTestLoop',
'testBuiltins',
];
const generateBundlesP = Promise.all(
CONTRACT_FILES.map(async contract => {
Expand Down Expand Up @@ -38,32 +39,58 @@ async function main(basedir, withSES, argv) {
return controller.dump();
}

const infiniteInstallLoopLog = ['installing infiniteInstallLoop'];
test('zoe - metering - infinite loop in installation', async t => {
try {
const dump = await main('zoe-metering', true, ['infiniteInstallLoop']);
t.deepEquals(dump.log, 'foo', 'log is correct');
t.deepEquals(dump.log, infiniteInstallLoopLog, 'log is correct');
} catch (e) {
t.isNot(e, e, 'unexpected exception');
} finally {
t.end();
}
});

const infiniteInstanceLoopLog = [
'installing infiniteInstanceLoop',
'instantiating infiniteInstanceLoop',
];
test('zoe - metering - infinite loop in instantiation', async t => {
try {
const dump = await main('zoe-metering', true, ['infiniteInstanceLoop']);
t.deepEquals(dump.log, 'foo', 'log is correct');
t.deepEquals(dump.log, infiniteInstanceLoopLog, 'log is correct');
} catch (e) {
t.isNot(e, e, 'unexpected exception');
} finally {
t.end();
}
});

const infiniteTestLoopLog = [
'installing infiniteTestLoop',
'instantiating infiniteTestLoop',
'invoking infiniteTestLoop.doTest()',
];
test('zoe - metering - infinite loop in contract method', async t => {
try {
const dump = await main('zoe-metering', true, ['infiniteTestLoop']);
t.deepEquals(dump.log, 'foo', 'log is correct');
t.deepEquals(dump.log, infiniteTestLoopLog, 'log is correct');
} catch (e) {
t.isNot(e, e, 'unexpected exception');
} finally {
t.end();
}
});

const testBuiltinsLog = [
'installing testBuiltins',
'instantiating testBuiltins',
'invoking testBuiltins.doTest()',
];
test('zoe - metering - expensive builtins in contract method', async t => {
try {
const dump = await main('zoe-metering', true, ['testBuiltins']);
t.deepEquals(dump.log, testBuiltinsLog, 'log is correct');
} catch (e) {
t.isNot(e, e, 'unexpected exception');
} finally {
Expand Down
17 changes: 17 additions & 0 deletions packages/zoe/test/swingsetTests/zoe-metering/testBuiltins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import harden from '@agoric/harden';

export const makeContract = (zoe, terms) => {
const seat = harden({});
const { invite } = zoe.makeInvite(seat, {
seatDesc: 'tester',
});
return harden({
publicAPI: {
doTest: () => {
new Array(1e7).map(Object.create);
},
},
invite,
terms,
});
}

0 comments on commit 9138801

Please sign in to comment.