Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Durable ZCF #5635

Merged
merged 21 commits into from
Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6fafffc
refactor: make zcf durable
erights Jul 3, 2022
eb5a903
chore: minor updates for tests and comments
Chris-Hibbert Jul 8, 2022
6276718
chore: more minor updates and integration
Chris-Hibbert Jul 8, 2022
03a9358
refactor: rename MakeNoEscrowSeat to MakeNoEscrowSeatKit
Chris-Hibbert Jul 8, 2022
a129074
test: disable loopback in paramGovernance test.
Chris-Hibbert Jul 8, 2022
7087d9e
test: repair bootstrap test for new way to start contracts
Chris-Hibbert Jul 8, 2022
d9d34c0
chore: cleanups from review
Chris-Hibbert Jul 13, 2022
33eb77f
chore: drop default to undefined
Chris-Hibbert Jul 13, 2022
9afde57
refactor: simplify upgradeable contract interface to start/vivify
Chris-Hibbert Jul 15, 2022
f5c029c
fix: suggestions for #5770
erights Jul 15, 2022
ff656aa
fix: added TODOs
erights Jul 15, 2022
d2f218e
chore: minor cleanups: types, names, TODOs, etc.
Chris-Hibbert Jul 15, 2022
d70db58
chore: clean up backquoted strings
Chris-Hibbert Jul 18, 2022
c6bc01c
refactor: switch assertDeposit() back to depositPayout()
Chris-Hibbert Jul 18, 2022
2593725
chore: review clean-ups
Chris-Hibbert Jul 18, 2022
28be701
chore: types fixes
turadg Jul 18, 2022
a3be63e
refactor(zcfMint): default zcfSeat for mintGains
turadg Jul 18, 2022
c38c45e
chore: contract includes "upgraded" in strings conditionally
Chris-Hibbert Jul 18, 2022
ba45800
chore: more reviews: comments, asserts, and strings
Chris-Hibbert Jul 18, 2022
f17a455
chore: drop atomicity TODOs. discussed and resolved.
Chris-Hibbert Jul 18, 2022
4f4c014
chore: minor clean-ups
Chris-Hibbert Jul 19, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {

import { AssetKind, makeDurableIssuerKit, vivifyIssuerKit } from '../../../src';

function vivifyErtpService(baggage, exitVatWithFailure) {
export const vivifyErtpService = (baggage, exitVatWithFailure) => {
const issuerBaggageSet = provideDurableSetStore(baggage, 'BaggageSet');
const ertpService = vivifySingleton(baggage, 'ERTPService', {
makeIssuerKit: (
Expand Down Expand Up @@ -38,7 +38,8 @@ function vivifyErtpService(baggage, exitVatWithFailure) {
}

return ertpService;
}
};
harden(vivifyErtpService);

export const buildRootObject = async (vatPowers, _vatParams, baggage) => {
const ertpService = vivifyErtpService(baggage, vatPowers.exitVatWithFailure);
Expand Down
2 changes: 1 addition & 1 deletion packages/SwingSet/src/supervisors/supervisor-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function makeSupervisorDispatch(dispatch) {
() => harden(['ok', null, null]),
err => {
// TODO react more thoughtfully, maybe terminate the vat
console.log(`error ${err} during vat dispatch() of ${delivery}`);
console.log(`error [${err}] during vat dispatch() of ${delivery}`);
return harden(['error', `${err}`, null]);
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import bundleSource from '@endo/bundle-source';
import buildManualTimer from '@agoric/zoe/tools/manualTimer.js';
import { makeFakeVatAdmin } from '@agoric/zoe/tools/fakeVatAdmin.js';
import { E } from '@endo/eventual-send';
import { makeLoopback } from '@endo/captp';

import { resolve as importMetaResolve } from 'import-meta-resolve';
import { MALLEABLE_NUMBER } from '../swingsetTests/contractGovernor/governedContract.js';
Expand All @@ -34,7 +33,7 @@ const voteCounterBundleP = makeBundle(voteCounterRoot);
const governedBundleP = makeBundle(governedRoot);

const setUpZoeForTest = async setJig => {
const { makeFar } = makeLoopback('zoeTest');
const makeFar = o => o;

/**
* These properties will be assigned by `setJig` in the contract.
Expand All @@ -44,7 +43,6 @@ const setUpZoeForTest = async setJig => {
* @property {IssuerRecord} runIssuerRecord
* @property {IssuerRecord} govIssuerRecord
*/

const { zoeService, feeMintAccess: nonFarFeeMintAccess } = makeZoeKit(
makeFakeVatAdmin(setJig, o => makeFar(o)).admin,
);
Expand Down
42 changes: 37 additions & 5 deletions packages/vat-data/src/kind-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { provide } from '@agoric/store';
import { defineDurableKind, makeKindHandle } from './vat-data-bindings.js';

/** @template L,R @typedef {import('@endo/eventual-send').RemotableBrand<L, R>} RemotableBrand */
/** @typedef {import('@agoric/store').MapStore<string,unknown>} Baggage */
/** @template T @typedef {import('./types.js').DefineKindOptions<T>} DefineKindOptions */
/** @template T @typedef {import('./types.js').KindFacet<T>} KindFacet */
/** @typedef {import('./types.js').DurableKindHandle} DurableKindHandle */

const { entries, fromEntries } = Object;

Expand All @@ -12,6 +16,11 @@ export const dropContext =
// @ts-expect-error TODO statically recognize harden
harden(dropContext);

/**
* @param {Baggage} baggage
* @param {string} kindName
* @returns {DurableKindHandle}
*/
export const provideKindHandle = (baggage, kindName) =>
provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName));
// @ts-expect-error TODO statically recognize harden
Expand Down Expand Up @@ -62,14 +71,37 @@ export const objectMap = (original, mapFn) => {
return /** @type {Record<K, U>} */ (harden(fromEntries(mapEnts)));
};

/** @typedef {import('@agoric/store').MapStore<string,unknown>} Baggage */
/**
* @template P,S,B
* @param {Baggage} baggage
* @param {string} kindName
* @param {(...args: P[]) => S} init
* @param {B} behavior
* @param {DefineKindOptions<unknown>} [options]
* @returns {(...args: P[]) => KindFacet<B>}
*/
export const vivifyKind = (
baggage,
kindName,
init,
behavior,
options = undefined,
) =>
defineDurableKind(
provideKindHandle(baggage, kindName),
init,
behavior,
options,
);
// @ts-expect-error TODO statically recognize harden
harden(vivifyKind);

/**
* @template T
* @param {Baggage} baggage
* @param {string} kindName
* @param {T} methods
* @param {import('./types.js').DefineKindOptions<unknown>} [options]
* @param {DefineKindOptions<unknown>} [options]
* @returns {T & RemotableBrand<{}, T>}
*/
export const vivifySingleton = (
Expand All @@ -78,10 +110,10 @@ export const vivifySingleton = (
methods,
options = undefined,
) => {
const kindHandle = provideKindHandle(baggage, kindName);
const behavior = objectMap(methods, dropContext);
const makeSingleton = defineDurableKind(
kindHandle,
const makeSingleton = vivifyKind(
baggage,
kindName,
() => ({}),
behavior,
options,
Expand Down
1 change: 0 additions & 1 deletion packages/vat-data/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export type DurableKindHandle = DurableKindHandleClass;
type DefineKindOptions<C> = {
finish?: (context: C) => void;
durable?: boolean;
fakeDurable?: boolean;
};

export type VatData = {
Expand Down
7 changes: 6 additions & 1 deletion packages/vats/src/core/basic-behaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,14 @@ export const installBootContracts = async ({
mintHolder,
walletFactory,
})) {
// This really wants to be E(vatAdminSvc).getBundleIDByName, but it's
// good enough to do D(vatAdmin).getBundleIDByName
const bundleCap = D(vatAdmin).getNamedBundleCap(name);

const bundle = D(bundleCap).getBundle();
producer.resolve(E(zoe).install(bundle));
// TODO (#4374) this should be E(zoe).installBundleID(bundleID);
const installation = E(zoe).install(bundle);
producer.resolve(installation);
}
};

Expand Down
9 changes: 6 additions & 3 deletions packages/vats/test/test-boot.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,22 @@ const testRole = (ROLE, governanceActions) => {
fakeBundleCaps.set(bundleCap, name);
return bundleCap;
};
const createVat = bundleCap => {
const createVat = (bundleCap, options) => {
const name = fakeBundleCaps.get(bundleCap);
assert(name);
switch (name) {
case 'zcf':
return fakeVatAdmin.createVat(zcfBundleCap);
return fakeVatAdmin.createVat(zcfBundleCap, options);
default: {
const buildRoot = vatRoots[name];
if (!buildRoot) {
throw Error(`TODO: load vat ${name}`);
}
const vatParameters = {};
const vatParameters = { ...options?.vatParameters };
if (name === 'zoe') {
// basic-behaviors.js:buildZoe() provides hard-coded zcf BundleName
// and vat-zoe.js ignores vatParameters, but this would be the
// preferred way to pass the name.
vatParameters.zcfBundleName = 'zcf';
}
return { root: buildRoot({}, vatParameters), admin: {} };
Expand Down
5 changes: 3 additions & 2 deletions packages/wallet/api/test/attestationExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import '@agoric/zoe/exported.js';
import { AmountMath } from '@agoric/ertp';
import { E } from '@endo/eventual-send';
import { Far } from '@endo/marshal';

/** @param {ZCF} zcf */
export const start = async zcf => {
Expand Down Expand Up @@ -53,12 +54,12 @@ export const start = async zcf => {

const getCallHistory = () => callHistory;

const publicFacet = {
const publicFacet = Far('attestation public facet', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this work without a Far declaration previously, before #5770 , as well as on master before #5635 ?

It is good now, so no change suggested. But I do not understand why things used to work.

mintAttestation,
makeWantAttInvitation,
makeReturnAttInvitation,
getCallHistory,
};
});

return harden({ publicFacet });
};
5 changes: 3 additions & 2 deletions packages/zoe/src/contractFacet/allocationMath.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// @ts-check
import { assert, details as X } from '@agoric/assert';
import { AmountMath } from '@agoric/ertp';

const { details: X } = assert;

/**
* @callback Operation
*
Expand Down Expand Up @@ -37,7 +38,7 @@ const doOperation = (allocation, amountKeywordRecord, operationFn) => {
})
.filter(([_keyword, result]) => result !== undefined);

return Object.fromEntries(entries);
return harden(Object.fromEntries(entries));
};

/** @type {Operation} */
Expand Down
2 changes: 1 addition & 1 deletion packages/zoe/src/contractFacet/internal-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

/**
* @typedef ZCFZygote
* @property {(bundleOrBundleCap: SourceBundle | BundleCap) => void} evaluateContract
* @property {(instanceAdminFromZoe: ERef<ZoeInstanceAdmin>,
* instanceRecordFromZoe: InstanceRecord,
* issuerStorageFromZoe: IssuerRecords,
* privateArgs?: object,
* ) => Promise<ExecuteContractResult>} startContract
* @property {(privateArgs?: object) => void} restartContract
*/
49 changes: 41 additions & 8 deletions packages/zoe/src/contractFacet/offerHandlerStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,56 @@

import { makeWeakStore } from '@agoric/store';
import { ToFarFunction } from '@endo/marshal';
import { canBeDurable, provideDurableWeakMapStore } from '@agoric/vat-data';

import { makeHandle } from '../makeHandle.js';
import { defineDurableHandle } from '../makeHandle.js';

export const makeOfferHandlerStorage = () => {
export const makeOfferHandlerStorage = zcfBaggage => {
const makeInvitationHandle = defineDurableHandle(zcfBaggage, 'Invitation');
/** @type {WeakStore<InvitationHandle, OfferHandler>} */
const invitationHandleToHandler = makeWeakStore('invitationHandle');

// ZCF needs to ephemerally hold on to ephemeral handlers, and durably hold
// onto handlers that are intended to be durable. We keep two stores and store
// each handler in the right one. When retrieving, we look for them in both.
// If Zoe restarts, the ephemeral ones will be lost, and the durable ones will
// survive.
const invitationHandleToEphemeralHandler = makeWeakStore(
'invitationHandleToEphemeralHandler',
);
/** @type {WeakStore<InvitationHandle, OfferHandler>} */
const invitationHandleToDurableHandler = provideDurableWeakMapStore(
zcfBaggage,
'invitationHandleToDurableHandler',
);

/** @type {(offerHandler: OfferHandler) => InvitationHandle} */
const storeOfferHandler = offerHandler => {
const farOfferHandler = ToFarFunction('offerHandler', offerHandler);
const invitationHandle = makeHandle('Invitation');
invitationHandleToHandler.init(invitationHandle, farOfferHandler);
if (typeof offerHandler === 'function') {
offerHandler = ToFarFunction('offerHandler', offerHandler);
}
const invitationHandleToHandler = canBeDurable(offerHandler)
? invitationHandleToDurableHandler
: invitationHandleToEphemeralHandler;

const invitationHandle = makeInvitationHandle();
invitationHandleToHandler.init(invitationHandle, offerHandler);
return invitationHandle;
};

/** @type {(invitationHandle: InvitationHandle) => OfferHandler} */
const takeOfferHandler = invitationHandle => {
/**
* @type {(invitationHandle: InvitationHandle, details?: Details) => OfferHandler}
*/
const takeOfferHandler = (
invitationHandle,
details = 'offerHandler may not have survived upgrade',
) => {
let invitationHandleToHandler;
if (invitationHandleToDurableHandler.has(invitationHandle)) {
invitationHandleToHandler = invitationHandleToDurableHandler;
} else {
assert(invitationHandleToEphemeralHandler.has(invitationHandle), details);
invitationHandleToHandler = invitationHandleToEphemeralHandler;
}
const offerHandler = invitationHandleToHandler.get(invitationHandle);
invitationHandleToHandler.delete(invitationHandle);
return offerHandler;
Expand Down
16 changes: 9 additions & 7 deletions packages/zoe/src/contractFacet/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
*/

/**
* @template {object} [OR=any] OR is OfferResult
* @template {object} [OR=unknown] OR is OfferResult
* @callback MakeInvitation
*
* Make a credible Zoe invitation for a particular smart contract
Expand Down Expand Up @@ -188,7 +188,7 @@
* @typedef {object} ZCFSeat
* @property {() => void} exit
* @property {ZCFSeatFail} fail
* @property {() => Notifier<Allocation>} getNotifier
* @property {() => Promise<Notifier<Allocation>>} getNotifier
* @property {() => boolean} hasExited
* @property {() => ProposalRecord} getProposal
* @property {ZCFGetAmountAllocated} getAmountAllocated
Expand All @@ -206,11 +206,13 @@
*/

/**
* @template {object} [OR=any]
* @callback OfferHandler
* @param {ZCFSeat} seat
* @param {object=} offerArgs
* @returns {OR}
* @template {object} OR Offer results
* @typedef {(seat: ZCFSeat, offerArgs?: object) => OR} HandleOffer
*/

/**
* @template {object} [OR=unknown] Offer results
* @typedef {HandleOffer<OR> | { handle: HandleOffer<OR> }} OfferHandler
*/

/**
Expand Down
Loading