From 648b297bc1f2578b38b539c626189235431d1ccc Mon Sep 17 00:00:00 2001 From: "Mark S. Miller" Date: Mon, 18 Jan 2021 19:09:06 -0800 Subject: [PATCH] Declare many of our remotables (#2178) * fix: Declare many of our remotables --- packages/ERTP/src/amountMath.js | 4 +- packages/ERTP/src/interfaces.js | 3 + packages/ERTP/src/issuer.js | 278 +++++++++--------- packages/ERTP/src/types.js | 14 + .../SwingSet/src/kernel/initializeKernel.js | 4 +- packages/SwingSet/src/kernel/liveSlots.js | 9 +- .../SwingSet/test/definition/vat-liveslots.js | 2 +- .../SwingSet/test/definition/vat-setup.js | 2 +- packages/SwingSet/test/test-controller.js | 8 +- packages/SwingSet/test/test-devices.js | 10 +- packages/SwingSet/test/test-liveslots.js | 3 +- packages/SwingSet/test/test-marshal.js | 15 +- packages/SwingSet/test/test-vpid-liveslots.js | 5 +- packages/captp/lib/captp.js | 7 +- packages/captp/test/test-crosstalk.js | 5 +- packages/captp/test/test-disco.js | 7 +- packages/captp/test/test-loopback.js | 21 +- .../cosmic-swingset/lib/ag-solo/vats/repl.js | 3 +- .../api/test/test-lib-dehydrate.js | 8 +- .../api/test/test-lib-wallet.js | 15 +- packages/marshal/index.js | 1 + packages/marshal/src/marshal.js | 47 ++- packages/marshal/test/test-marshal.js | 9 +- .../demo/vatResolveTest/bootstrap.js | 9 +- packages/swingset-runner/package.json | 1 + .../zoe/src/contractFacet/contractFacet.js | 2 +- packages/zoe/src/contractFacet/seat.js | 3 +- packages/zoe/src/makeHandle.js | 3 +- packages/zoe/src/types.js | 2 +- packages/zoe/src/zoeService/types.js | 2 +- packages/zoe/src/zoeService/zoe.js | 19 +- packages/zoe/src/zoeService/zoeSeat.js | 5 +- .../contractSupport/test-zoeHelpers.js | 9 +- 33 files changed, 308 insertions(+), 227 deletions(-) diff --git a/packages/ERTP/src/amountMath.js b/packages/ERTP/src/amountMath.js index fffabbe811d..5d6a12c459f 100644 --- a/packages/ERTP/src/amountMath.js +++ b/packages/ERTP/src/amountMath.js @@ -1,7 +1,7 @@ // @ts-check import { assert, details } from '@agoric/assert'; - +import { Far } from '@agoric/marshal'; import { mustBeComparable } from '@agoric/same-structure'; import './types'; @@ -94,7 +94,7 @@ function makeAmountMath(brand, amountMathKind) { const cache = new WeakSet(); /** @type {AmountMath} */ - const amountMath = harden({ + const amountMath = Far('amountMath', { getBrand: () => brand, getAmountMathKind: () => amountMathKind, diff --git a/packages/ERTP/src/interfaces.js b/packages/ERTP/src/interfaces.js index 7af1a69df34..ca466c1297d 100644 --- a/packages/ERTP/src/interfaces.js +++ b/packages/ERTP/src/interfaces.js @@ -11,6 +11,9 @@ export const ERTPKind = { DEPOSIT_FACET: 'depositFacet', }; +/** @type {MakeFarName} */ +export const makeFarName = (allegedName, kind) => `${allegedName} ${kind}`; + /** @type {MakeInterface} */ export const makeInterface = (allegedName, kind) => `Alleged: ${allegedName} ${kind}`; diff --git a/packages/ERTP/src/issuer.js b/packages/ERTP/src/issuer.js index cefb97b1de5..174f212bd81 100644 --- a/packages/ERTP/src/issuer.js +++ b/packages/ERTP/src/issuer.js @@ -5,12 +5,12 @@ import { assert, details } from '@agoric/assert'; import { makeExternalStore } from '@agoric/store'; import { E } from '@agoric/eventual-send'; -import { Remotable } from '@agoric/marshal'; +import { Far } from '@agoric/marshal'; import { makeNotifierKit } from '@agoric/notifier'; import { isPromise } from '@agoric/promise-kit'; import { makeAmountMath, MathKind } from './amountMath'; -import { makeInterface, ERTPKind } from './interfaces'; +import { makeFarName, ERTPKind } from './interfaces'; import { coerceDisplayInfo } from './displayInfo'; import './types'; @@ -26,22 +26,18 @@ function makeIssuerKit( assert.typeof(allegedName, 'string'); displayInfo = coerceDisplayInfo(displayInfo); - const brand = Remotable( - makeInterface(allegedName, ERTPKind.BRAND), - undefined, - { - isMyIssuer: allegedIssuerP => { - return E.when(allegedIssuerP, allegedIssuer => { - // eslint-disable-next-line no-use-before-define - return allegedIssuer === issuer; - }); - }, - getAllegedName: () => allegedName, - - // Give information to UI on how to display the amount. - getDisplayInfo: () => displayInfo, + const brand = Far(makeFarName(allegedName, ERTPKind.BRAND), { + isMyIssuer: allegedIssuerP => { + return E.when(allegedIssuerP, allegedIssuer => { + // eslint-disable-next-line no-use-before-define + return allegedIssuer === issuer; + }); }, - ); + getAllegedName: () => allegedName, + + // Give information to UI on how to display the amount. + getDisplayInfo: () => displayInfo, + }); const amountMath = makeAmountMath(brand, amountMathKind); const { add } = amountMath; @@ -51,7 +47,7 @@ function makeIssuerKit( makeInstance: makePayment, makeWeakStore: makePaymentWeakStore, } = makeExternalStore('payment', () => - Remotable(makeInterface(allegedName, ERTPKind.PAYMENT), undefined, { + Far(makeFarName(allegedName, ERTPKind.PAYMENT), { getAllegedBrand: () => brand, }), ); @@ -85,7 +81,7 @@ function makeIssuerKit( * @returns {DepositFacet} */ purse => - Remotable(makeInterface(allegedName, ERTPKind.DEPOSIT_FACET), undefined, { + Far(makeFarName(allegedName, ERTPKind.DEPOSIT_FACET), { receive: purse.deposit, }), ); @@ -99,51 +95,47 @@ function makeIssuerKit( } = makeNotifierKit(currentBalance); /** @type {Purse} */ - const purse = Remotable( - makeInterface(allegedName, ERTPKind.PURSE), - undefined, - { - deposit: (srcPayment, optAmount = undefined) => { - if (isPromise(srcPayment)) { - throw new TypeError( - `deposit does not accept promises as first argument. Instead of passing the promise (deposit(paymentPromise)), consider unwrapping the promise first: paymentPromise.then(actualPayment => deposit(actualPayment))`, - ); - } - assertKnownPayment(srcPayment); - const srcPaymentBalance = paymentLedger.get(srcPayment); - // Note: this does not guarantee that optAmount itself is a valid stable amount - assertAmountEqual(srcPaymentBalance, optAmount); - const newPurseBalance = amountMath.add( - srcPaymentBalance, - currentBalance, + const purse = Far(makeFarName(allegedName, ERTPKind.PURSE), { + deposit: (srcPayment, optAmount = undefined) => { + if (isPromise(srcPayment)) { + throw new TypeError( + `deposit does not accept promises as first argument. Instead of passing the promise (deposit(paymentPromise)), consider unwrapping the promise first: paymentPromise.then(actualPayment => deposit(actualPayment))`, ); - // Commit point - // Move the assets in `srcPayment` into this purse, using up the - // source payment, such that total assets are conserved. - paymentLedger.delete(srcPayment); - currentBalance = newPurseBalance; - balanceUpdater.updateState(currentBalance); - return srcPaymentBalance; - }, - withdraw: amount => { - amount = amountMath.coerce(amount); - const newPurseBalance = amountMath.subtract(currentBalance, amount); - const payment = makePayment(); - // Commit point - // Move the withdrawn assets from this purse into a new payment - // which is returned. Total assets must remain conserved. - currentBalance = newPurseBalance; - balanceUpdater.updateState(currentBalance); - paymentLedger.init(payment, amount); - return payment; - }, - getCurrentAmount: () => currentBalance, - getCurrentAmountNotifier: () => balanceNotifier, - getAllegedBrand: () => brand, - // eslint-disable-next-line no-use-before-define - getDepositFacet: () => depositFacet, + } + assertKnownPayment(srcPayment); + const srcPaymentBalance = paymentLedger.get(srcPayment); + // Note: this does not guarantee that optAmount itself is a valid stable amount + assertAmountEqual(srcPaymentBalance, optAmount); + const newPurseBalance = amountMath.add( + srcPaymentBalance, + currentBalance, + ); + // Commit point + // Move the assets in `srcPayment` into this purse, using up the + // source payment, such that total assets are conserved. + paymentLedger.delete(srcPayment); + currentBalance = newPurseBalance; + balanceUpdater.updateState(currentBalance); + return srcPaymentBalance; }, - ); + withdraw: amount => { + amount = amountMath.coerce(amount); + const newPurseBalance = amountMath.subtract(currentBalance, amount); + const payment = makePayment(); + // Commit point + // Move the withdrawn assets from this purse into a new payment + // which is returned. Total assets must remain conserved. + currentBalance = newPurseBalance; + balanceUpdater.updateState(currentBalance); + paymentLedger.init(payment, amount); + return payment; + }, + getCurrentAmount: () => currentBalance, + getCurrentAmountNotifier: () => balanceNotifier, + getAllegedBrand: () => brand, + // eslint-disable-next-line no-use-before-define + getDepositFacet: () => depositFacet, + }); const depositFacet = makeDepositFacet(purse); return purse; @@ -201,95 +193,89 @@ function makeIssuerKit( }; /** @type {Issuer} */ - const issuer = Remotable( - makeInterface(allegedName, ERTPKind.ISSUER), - undefined, - { - getBrand: () => brand, - getAllegedName: () => allegedName, - getAmountMathKind: () => amountMathKind, - makeEmptyPurse: makePurse, + const issuer = Far(makeFarName(allegedName, ERTPKind.ISSUER), { + getBrand: () => brand, + getAllegedName: () => allegedName, + getAmountMathKind: () => amountMathKind, + makeEmptyPurse: makePurse, - isLive: paymentP => { - return E.when(paymentP, payment => { - return paymentLedger.has(payment); - }); - }, - getAmountOf: paymentP => { - return E.when(paymentP, payment => { - assertKnownPayment(payment); - return paymentLedger.get(payment); - }); - }, + isLive: paymentP => { + return E.when(paymentP, payment => { + return paymentLedger.has(payment); + }); + }, + getAmountOf: paymentP => { + return E.when(paymentP, payment => { + assertKnownPayment(payment); + return paymentLedger.get(payment); + }); + }, - burn: (paymentP, optAmount = undefined) => { - return E.when(paymentP, payment => { - assertKnownPayment(payment); - const paymentBalance = paymentLedger.get(payment); - assertAmountEqual(paymentBalance, optAmount); - // Commit point. - paymentLedger.delete(payment); - return paymentBalance; - }); - }, - claim: (paymentP, optAmount = undefined) => { - return E.when(paymentP, srcPayment => { - assertKnownPayment(srcPayment); - const srcPaymentBalance = paymentLedger.get(srcPayment); - assertAmountEqual(srcPaymentBalance, optAmount); - // Commit point. - const [payment] = reallocate([srcPayment], [srcPaymentBalance]); - return payment; - }); - }, - // Payments in `fromPaymentsPArray` must be distinct. Alias - // checking is delegated to the `reallocate` function. - combine: (fromPaymentsPArray, optTotalAmount = undefined) => { - return Promise.all(fromPaymentsPArray).then(fromPaymentsArray => { - fromPaymentsArray.every(assertKnownPayment); - const totalPaymentsBalance = fromPaymentsArray - .map(paymentLedger.get) - .reduce(add, empty); - assertAmountEqual(totalPaymentsBalance, optTotalAmount); - // Commit point. - const [payment] = reallocate(fromPaymentsArray, [ - totalPaymentsBalance, - ]); - return payment; - }); - }, - // payment to two payments, A and B - split: (paymentP, paymentAmountA) => { - return E.when(paymentP, srcPayment => { - paymentAmountA = amountMath.coerce(paymentAmountA); - assertKnownPayment(srcPayment); - const srcPaymentBalance = paymentLedger.get(srcPayment); - const paymentAmountB = amountMath.subtract( - srcPaymentBalance, - paymentAmountA, - ); - // Commit point - const newPayments = reallocate( - [srcPayment], - [paymentAmountA, paymentAmountB], - ); - return newPayments; - }); - }, - splitMany: (paymentP, amounts) => { - return E.when(paymentP, srcPayment => { - assertKnownPayment(srcPayment); - amounts = amounts.map(amountMath.coerce); - // Commit point - const newPayments = reallocate([srcPayment], amounts); - return newPayments; - }); - }, + burn: (paymentP, optAmount = undefined) => { + return E.when(paymentP, payment => { + assertKnownPayment(payment); + const paymentBalance = paymentLedger.get(payment); + assertAmountEqual(paymentBalance, optAmount); + // Commit point. + paymentLedger.delete(payment); + return paymentBalance; + }); }, - ); + claim: (paymentP, optAmount = undefined) => { + return E.when(paymentP, srcPayment => { + assertKnownPayment(srcPayment); + const srcPaymentBalance = paymentLedger.get(srcPayment); + assertAmountEqual(srcPaymentBalance, optAmount); + // Commit point. + const [payment] = reallocate([srcPayment], [srcPaymentBalance]); + return payment; + }); + }, + // Payments in `fromPaymentsPArray` must be distinct. Alias + // checking is delegated to the `reallocate` function. + combine: (fromPaymentsPArray, optTotalAmount = undefined) => { + return Promise.all(fromPaymentsPArray).then(fromPaymentsArray => { + fromPaymentsArray.every(assertKnownPayment); + const totalPaymentsBalance = fromPaymentsArray + .map(paymentLedger.get) + .reduce(add, empty); + assertAmountEqual(totalPaymentsBalance, optTotalAmount); + // Commit point. + const [payment] = reallocate(fromPaymentsArray, [totalPaymentsBalance]); + return payment; + }); + }, + // payment to two payments, A and B + split: (paymentP, paymentAmountA) => { + return E.when(paymentP, srcPayment => { + paymentAmountA = amountMath.coerce(paymentAmountA); + assertKnownPayment(srcPayment); + const srcPaymentBalance = paymentLedger.get(srcPayment); + const paymentAmountB = amountMath.subtract( + srcPaymentBalance, + paymentAmountA, + ); + // Commit point + const newPayments = reallocate( + [srcPayment], + [paymentAmountA, paymentAmountB], + ); + return newPayments; + }); + }, + splitMany: (paymentP, amounts) => { + return E.when(paymentP, srcPayment => { + assertKnownPayment(srcPayment); + amounts = amounts.map(amountMath.coerce); + // Commit point + const newPayments = reallocate([srcPayment], amounts); + return newPayments; + }); + }, + }); /** @type {Mint} */ - const mint = Remotable(makeInterface(allegedName, ERTPKind.MINT), undefined, { + const mint = Far(makeFarName(allegedName, ERTPKind.MINT), { getIssuer: () => issuer, mintPayment: newAmount => { newAmount = amountMath.coerce(newAmount); diff --git a/packages/ERTP/src/types.js b/packages/ERTP/src/types.js index ff01e9d8125..9ac103f6b30 100644 --- a/packages/ERTP/src/types.js +++ b/packages/ERTP/src/types.js @@ -354,3 +354,17 @@ * @param {string} kind The ERTPKind * @returns {InterfaceSpec} */ + +/** + * @callback MakeFarName + * Make the farName using the allegedName and kind. The particular + * structure may change in the future to be more sophisticated. + * Therefore, ERTP and Zoe should not depend on this particular + * implementation. `makeFar` converts its farName argument into + * the iface argument it passes to `Remotable`. + * + * @param {string} allegedName The allegedName, as passed to + * `makeIssuerKit` + * @param {string} kind The ERTPKind + * @returns {string} + */ diff --git a/packages/SwingSet/src/kernel/initializeKernel.js b/packages/SwingSet/src/kernel/initializeKernel.js index 68dba9d3b7b..2e1daa457bb 100644 --- a/packages/SwingSet/src/kernel/initializeKernel.js +++ b/packages/SwingSet/src/kernel/initializeKernel.js @@ -1,6 +1,6 @@ /* eslint-disable no-use-before-define */ -import { makeMarshal } from '@agoric/marshal'; +import { makeMarshal, Far } from '@agoric/marshal'; import { assert } from '@agoric/assert'; import { assertKnownOptions } from '../assertOptions'; import { insistVatID } from './id'; @@ -133,7 +133,7 @@ export function initializeKernel(config, hostStorage, verbose = false) { // non-empty object as vatObj0s, since an empty object would be // serialized as pass-by-presence. It wouldn't make much sense for the // bootstrap object to call itself, though. - const vref = harden({ + const vref = Far('vref', { toString() { return name; }, diff --git a/packages/SwingSet/src/kernel/liveSlots.js b/packages/SwingSet/src/kernel/liveSlots.js index 9abefb42466..f3fb1fd2c1b 100644 --- a/packages/SwingSet/src/kernel/liveSlots.js +++ b/packages/SwingSet/src/kernel/liveSlots.js @@ -3,6 +3,7 @@ import { QCLASS, Remotable, + Far, getInterfaceOf, mustPassByPresence, makeMarshal, @@ -614,7 +615,13 @@ export function makeLiveSlots( vatParameters = harden({}), cacheSize = DEFAULT_VIRTUAL_OBJECT_CACHE_SIZE, ) { - const allVatPowers = { ...vatPowers, getInterfaceOf, Remotable, makeMarshal }; + const allVatPowers = { + ...vatPowers, + getInterfaceOf, + Remotable, + Far, + makeMarshal, + }; const r = build(syscall, forVatID, cacheSize, allVatPowers, vatParameters); const { vatGlobals, dispatch, setBuildRootObject } = r; // omit 'm' return harden({ vatGlobals, dispatch, setBuildRootObject }); diff --git a/packages/SwingSet/test/definition/vat-liveslots.js b/packages/SwingSet/test/definition/vat-liveslots.js index 9f70c7f0155..79521c5032a 100644 --- a/packages/SwingSet/test/definition/vat-liveslots.js +++ b/packages/SwingSet/test/definition/vat-liveslots.js @@ -11,7 +11,7 @@ export function buildRootObject(vatPowers) { return vatPowers.transformTildot('x~.foo(arg1)'); }, remotable() { - const r = vatPowers.Remotable('Alleged: iface1'); + const r = vatPowers.Far('iface1'); return vatPowers.getInterfaceOf(r); }, }); diff --git a/packages/SwingSet/test/definition/vat-setup.js b/packages/SwingSet/test/definition/vat-setup.js index 9f70c7f0155..79521c5032a 100644 --- a/packages/SwingSet/test/definition/vat-setup.js +++ b/packages/SwingSet/test/definition/vat-setup.js @@ -11,7 +11,7 @@ export function buildRootObject(vatPowers) { return vatPowers.transformTildot('x~.foo(arg1)'); }, remotable() { - const r = vatPowers.Remotable('Alleged: iface1'); + const r = vatPowers.Far('iface1'); return vatPowers.getInterfaceOf(r); }, }); diff --git a/packages/SwingSet/test/test-controller.js b/packages/SwingSet/test/test-controller.js index f01c6082f54..4242665658b 100644 --- a/packages/SwingSet/test/test-controller.js +++ b/packages/SwingSet/test/test-controller.js @@ -141,7 +141,7 @@ test('bootstrap export', async t => { method: 'bootstrap', args: { body: - '[{"bootstrap":{"@qclass":"slot","index":0},"comms":{"@qclass":"slot","index":1},"left":{"@qclass":"slot","index":2},"right":{"@qclass":"slot","index":3},"timer":{"@qclass":"slot","index":4},"vatAdmin":{"@qclass":"slot","index":5},"vattp":{"@qclass":"slot","index":6}},{"vatAdmin":{"@qclass":"slot","index":7}}]', + '[{"bootstrap":{"@qclass":"slot","iface":"Alleged: vref","index":0},"comms":{"@qclass":"slot","iface":"Alleged: vref","index":1},"left":{"@qclass":"slot","iface":"Alleged: vref","index":2},"right":{"@qclass":"slot","iface":"Alleged: vref","index":3},"timer":{"@qclass":"slot","iface":"Alleged: vref","index":4},"vatAdmin":{"@qclass":"slot","iface":"Alleged: vref","index":5},"vattp":{"@qclass":"slot","iface":"Alleged: vref","index":6}},{"vatAdmin":{"@qclass":"slot","index":7}}]', slots: [ boot0, comms0, @@ -182,8 +182,7 @@ test('bootstrap export', async t => { msg: { method: 'foo', args: { - body: - '[1,{"@qclass":"slot","iface":"Alleged: presence o-52","index":0}]', + body: '[1,{"@qclass":"slot","iface":"Alleged: vref","index":0}]', slots: [right0], }, result: fooP, @@ -205,8 +204,7 @@ test('bootstrap export', async t => { msg: { method: 'bar', args: { - body: - '[2,{"@qclass":"slot","iface":"Alleged: presence o-52","index":0}]', + body: '[2,{"@qclass":"slot","iface":"Alleged: vref","index":0}]', slots: [right0], }, result: barP, diff --git a/packages/SwingSet/test/test-devices.js b/packages/SwingSet/test/test-devices.js index 9b31ff00d84..157f10accff 100644 --- a/packages/SwingSet/test/test-devices.js +++ b/packages/SwingSet/test/test-devices.js @@ -62,11 +62,11 @@ test.serial('d0', async t => { // console.log(util.inspect(c.dump(), { depth: null })); t.deepEqual(JSON.parse(c.dump().log[0]), [ { - bootstrap: { '@qclass': 'slot', index: 0 }, - comms: { '@qclass': 'slot', index: 1 }, - timer: { '@qclass': 'slot', index: 2 }, - vatAdmin: { '@qclass': 'slot', index: 3 }, - vattp: { '@qclass': 'slot', index: 4 }, + bootstrap: { '@qclass': 'slot', iface: 'Alleged: vref', index: 0 }, + comms: { '@qclass': 'slot', iface: 'Alleged: vref', index: 1 }, + timer: { '@qclass': 'slot', iface: 'Alleged: vref', index: 2 }, + vatAdmin: { '@qclass': 'slot', iface: 'Alleged: vref', index: 3 }, + vattp: { '@qclass': 'slot', iface: 'Alleged: vref', index: 4 }, }, { d0: { '@qclass': 'slot', index: 5 }, diff --git a/packages/SwingSet/test/test-liveslots.js b/packages/SwingSet/test/test-liveslots.js index 8a89d71e08d..0fe92d86e18 100644 --- a/packages/SwingSet/test/test-liveslots.js +++ b/packages/SwingSet/test/test-liveslots.js @@ -1,6 +1,7 @@ import '@agoric/install-ses'; import test from 'ava'; import { E } from '@agoric/eventual-send'; +import { Far } from '@agoric/marshal'; import { WeakRef, FinalizationRegistry } from '../src/weakref'; import { waitUntilQuiescent } from '../src/waitUntilQuiescent'; import { makeLiveSlots } from '../src/kernel/liveSlots'; @@ -190,7 +191,7 @@ test('liveslots pipeline/non-pipeline calls', async t => { function build(_vatPowers) { let p1; - return harden({ + return Far('onetwo', { one(p) { p1 = p; E(p1).pipe1(); diff --git a/packages/SwingSet/test/test-marshal.js b/packages/SwingSet/test/test-marshal.js index 4a99dc292a0..c658299a0fa 100644 --- a/packages/SwingSet/test/test-marshal.js +++ b/packages/SwingSet/test/test-marshal.js @@ -1,4 +1,5 @@ import '@agoric/install-ses'; +import { Far } from '@agoric/marshal'; import test from 'ava'; import { makePromiseKit } from '@agoric/promise-kit'; @@ -18,23 +19,25 @@ async function prep() { test('serialize exports', t => { const { m } = makeMarshaller(undefined, gcTools); const ser = val => m.serialize(val); - const o1 = harden({}); - const o2 = harden({ + const o1 = Far('o1', {}); + const o2 = Far('o2', { meth1() { return 4; }, }); t.deepEqual(ser(o1), { - body: '{"@qclass":"slot","index":0}', + body: '{"@qclass":"slot","iface":"Alleged: o1","index":0}', slots: ['o+1'], }); // m now remembers that o1 is exported as 1 t.deepEqual(ser(harden([o1, o1])), { - body: '[{"@qclass":"slot","index":0},{"@qclass":"ibid","index":1}]', + body: + '[{"@qclass":"slot","iface":"Alleged: o1","index":0},{"@qclass":"ibid","index":1}]', slots: ['o+1'], }); t.deepEqual(ser(harden([o2, o1])), { - body: '[{"@qclass":"slot","index":0},{"@qclass":"slot","index":1}]', + body: + '[{"@qclass":"slot","iface":"Alleged: o2","index":0},{"@qclass":"slot","iface":"Alleged: o1","index":1}]', slots: ['o+2', 'o+1'], }); }); @@ -67,7 +70,7 @@ test('deserialize imports', async t => { test('deserialize exports', t => { const { m } = makeMarshaller(undefined, gcTools); - const o1 = harden({}); + const o1 = Far('o1', {}); m.serialize(o1); // allocates slot=1 const a = m.unserialize({ body: '{"@qclass":"slot","index":0}', diff --git a/packages/SwingSet/test/test-vpid-liveslots.js b/packages/SwingSet/test/test-vpid-liveslots.js index 2f3843cc491..9d1923b1d45 100644 --- a/packages/SwingSet/test/test-vpid-liveslots.js +++ b/packages/SwingSet/test/test-vpid-liveslots.js @@ -3,6 +3,7 @@ import '@agoric/install-ses'; import test from 'ava'; +import { Far } from '@agoric/marshal'; import { E } from '@agoric/eventual-send'; import { makePromiseKit } from '@agoric/promise-kit'; @@ -117,7 +118,7 @@ function resolvePR(pr, mode, targets) { break; case 'local-object': pr.resolve( - harden({ + Far('vpid resolve test', { two() { /* console.log(`local two() called`); */ }, @@ -595,7 +596,7 @@ async function doVatResolveCase4(t, mode) { function build(_vatPowers) { let p1; - return harden({ + return Far('test vpid', { async get(p) { p1 = p; // if we don't add this, node will complain when the kernel notifies diff --git a/packages/captp/lib/captp.js b/packages/captp/lib/captp.js index 55ad113b570..54fdbec9c35 100644 --- a/packages/captp/lib/captp.js +++ b/packages/captp/lib/captp.js @@ -6,6 +6,7 @@ // Defects in it are mfig's fault. import { Remotable as defaultRemotable, + Far as defaultFar, makeMarshal as defaultMakeMarshal, QCLASS, } from '@agoric/marshal'; @@ -23,6 +24,7 @@ export { E }; * @typedef {Object} CapTPOptions the options to makeCapTP * @property {(err: any) => void} onReject * @property {typeof defaultRemotable} Remotable + * @property {typeof defaultFar} Far * @property {typeof defaultMakeMarshal} makeMarshal * @property {number} epoch */ @@ -411,15 +413,16 @@ export function makeLoopback(ourId) { let nextNonce = 0; const nonceToRef = new Map(); + // TODO use the correct Far, which is not currently in scope here. const bootstrap = harden({ - refGetter: { + refGetter: defaultFar('captp bootstrap', { getRef(nonce) { // Find the local ref for the specified nonce. const xFar = nonceToRef.get(nonce); nonceToRef.delete(nonce); return xFar; }, - }, + }), }); // Create the tunnel. diff --git a/packages/captp/test/test-crosstalk.js b/packages/captp/test/test-crosstalk.js index a76c43472ea..cd079e25c44 100644 --- a/packages/captp/test/test-crosstalk.js +++ b/packages/captp/test/test-crosstalk.js @@ -1,11 +1,12 @@ import '@agoric/install-ses'; +import { Far } from '@agoric/marshal'; import test from 'ava'; import { makeLoopback, E } from '../lib/captp'; test('prevent crosstalk', async t => { const { makeFar } = makeLoopback('alice'); const rightRef = makeFar( - harden({ + Far('rightRef', { isSide(objP, side) { return E(objP) .side() @@ -18,7 +19,7 @@ test('prevent crosstalk', async t => { ); await E(rightRef).isSide(rightRef, 'right'); - const leftRef = harden({ + const leftRef = Far('leftRef', { side() { return 'left'; }, diff --git a/packages/captp/test/test-disco.js b/packages/captp/test/test-disco.js index b9b2c3b3e96..e073a43d2e8 100644 --- a/packages/captp/test/test-disco.js +++ b/packages/captp/test/test-disco.js @@ -1,4 +1,5 @@ import '@agoric/install-ses'; +import { Far } from '@agoric/marshal'; import test from 'ava'; import { E, makeCapTP } from '../lib/captp'; @@ -8,8 +9,9 @@ test('try disconnecting captp', async t => { const { getBootstrap, abort } = makeCapTP( 'us', obj => objs.push(obj), + // TODO Can we avoid the function wrapper? makeCapTP does the needed test () => - harden({ + Far('test hello', { method() { return 'hello'; }, @@ -68,8 +70,9 @@ test('try aborting captp with reason', async t => { const { getBootstrap, abort } = makeCapTP( 'us', obj => objs.push(obj), + // TODO Can we avoid the function wrapper? makeCapTP does the needed test () => - harden({ + Far('test hello', { method() { return 'hello'; }, diff --git a/packages/captp/test/test-loopback.js b/packages/captp/test/test-loopback.js index 2f59d7c14a7..ae6b108fe3f 100644 --- a/packages/captp/test/test-loopback.js +++ b/packages/captp/test/test-loopback.js @@ -1,4 +1,5 @@ import '@agoric/install-ses'; +import { Far } from '@agoric/marshal'; import test from 'ava'; import { E, makeLoopback } from '../lib/captp'; @@ -10,7 +11,7 @@ test('try loopback captp', async t => { }); const syncHandle = harden({}); - const syncAccess = { + const syncAccess = Far('syncAccess', { checkHandle(hnd) { // console.log('check', hnd, oobHandle); return hnd === syncHandle; @@ -21,28 +22,30 @@ test('try loopback captp', async t => { getHandle() { return syncHandle; }, - }; + }); const { makeFar } = makeLoopback('dean'); const objNear = harden({ promise: pr.p, syncAccess, - encourager: { + encourager: Far('encourager', { encourage(name) { const bang = new Promise(resolve => { setTimeout( () => - resolve({ - trigger() { - return `${name} BANG!`; - }, - }), + resolve( + Far('triggerObj', { + trigger() { + return `${name} BANG!`; + }, + }), + ), 200, ); }); return { comment: `good work, ${name}`, bang }; }, - }, + }), }); // Mark obj as far. diff --git a/packages/cosmic-swingset/lib/ag-solo/vats/repl.js b/packages/cosmic-swingset/lib/ag-solo/vats/repl.js index 74528ff5421..b6466d9e421 100644 --- a/packages/cosmic-swingset/lib/ag-solo/vats/repl.js +++ b/packages/cosmic-swingset/lib/ag-solo/vats/repl.js @@ -82,7 +82,7 @@ export function getReplHandler(replObjects, send, vatPowers) { // We use getInterfaceOf locally, and transformTildot is baked into the // Compartment we use to evaluate REPL inputs. We provide getInterfaceOf // and Remotable to REPL input code. - const { getInterfaceOf, Remotable, transformTildot } = vatPowers; + const { getInterfaceOf, Remotable, Far, transformTildot } = vatPowers; let highestHistory = -1; const commands = { [highestHistory]: '', @@ -154,6 +154,7 @@ export function getReplHandler(replObjects, send, vatPowers) { const endowments = { Remotable, + Far, getInterfaceOf, console: replConsole, E, diff --git a/packages/dapp-svelte-wallet/api/test/test-lib-dehydrate.js b/packages/dapp-svelte-wallet/api/test/test-lib-dehydrate.js index 08bace20dfb..057afd229bc 100644 --- a/packages/dapp-svelte-wallet/api/test/test-lib-dehydrate.js +++ b/packages/dapp-svelte-wallet/api/test/test-lib-dehydrate.js @@ -1,6 +1,7 @@ import '@agoric/install-ses'; // calls lockdown() // eslint-disable-next-line import/no-extraneous-dependencies import test from 'ava'; +import { Far } from '@agoric/marshal'; import { makeDehydrator } from '../src/lib-dehydrate'; @@ -77,7 +78,7 @@ test('makeDehydrator', async t => { ); const makeMockBrand = () => - harden({ + Far('mock brand', { isMyIssuer: _allegedIssuer => {}, getAllegedName: () => {}, }); @@ -121,7 +122,8 @@ test('makeDehydrator', async t => { t.deepEqual( dehydrate(harden({ brand: brand1, value: 40 })), harden({ - body: '{"brand":{"@qclass":"slot","index":0},"value":40}', + body: + '{"brand":{"@qclass":"slot","iface":"Alleged: mock brand","index":0},"value":40}', slots: [{ kind: 'brand', petname: 'moola' }], }), `serialize brand with petname`, @@ -155,7 +157,7 @@ test('makeDehydrator', async t => { dehydrate(proposal), { body: - '{"want":{"Asset1":{"brand":{"@qclass":"slot","index":0},"value":60},"Asset2":{"brand":{"@qclass":"slot","index":1},"value":{"instanceHandle":{"@qclass":"slot","index":2}}}},"give":{"Price":{"brand":{"@qclass":"slot","index":3},"value":3}},"exit":{"afterDeadline":{"timer":{"@qclass":"slot","index":4},"deadline":55}}}', + '{"want":{"Asset1":{"brand":{"@qclass":"slot","iface":"Alleged: mock brand","index":0},"value":60},"Asset2":{"brand":{"@qclass":"slot","iface":"Alleged: mock brand","index":1},"value":{"instanceHandle":{"@qclass":"slot","index":2}}}},"give":{"Price":{"brand":{"@qclass":"slot","iface":"Alleged: mock brand","index":3},"value":3}},"exit":{"afterDeadline":{"timer":{"@qclass":"slot","index":4},"deadline":55}}}', slots: [ { kind: 'brand', petname: 'moola' }, { kind: 'brand', petname: 'zoeInvite' }, diff --git a/packages/dapp-svelte-wallet/api/test/test-lib-wallet.js b/packages/dapp-svelte-wallet/api/test/test-lib-wallet.js index 234f5136137..9594eb293c6 100644 --- a/packages/dapp-svelte-wallet/api/test/test-lib-wallet.js +++ b/packages/dapp-svelte-wallet/api/test/test-lib-wallet.js @@ -330,7 +330,7 @@ test('lib-wallet dapp suggests issuer, instance, installation petnames', async t ], currentAmountSlots: { body: - '{"brand":{"@qclass":"slot","iface":"Alleged: Zoe Invitation brand","index":0},"value":[{"description":"getRefund","handle":{"@qclass":"slot","index":1},"instance":{"@qclass":"slot","index":2},"installation":{"@qclass":"slot","index":3}}]}', + '{"brand":{"@qclass":"slot","iface":"Alleged: Zoe Invitation brand","index":0},"value":[{"description":"getRefund","handle":{"@qclass":"slot","index":1},"instance":{"@qclass":"slot","iface":"Alleged: InstanceHandle","index":2},"installation":{"@qclass":"slot","iface":"Alleged: Installation","index":3}}]}', slots: [ { kind: 'brand', petname: 'zoe invite' }, { kind: 'unnamed', petname: 'unnamed-4' }, @@ -412,7 +412,7 @@ test('lib-wallet dapp suggests issuer, instance, installation petnames', async t ], currentAmountSlots: { body: - '{"brand":{"@qclass":"slot","iface":"Alleged: Zoe Invitation brand","index":0},"value":[{"description":"getRefund","handle":{"@qclass":"slot","index":1},"instance":{"@qclass":"slot","index":2},"installation":{"@qclass":"slot","index":3}}]}', + '{"brand":{"@qclass":"slot","iface":"Alleged: Zoe Invitation brand","index":0},"value":[{"description":"getRefund","handle":{"@qclass":"slot","index":1},"instance":{"@qclass":"slot","iface":"Alleged: InstanceHandle","index":2},"installation":{"@qclass":"slot","iface":"Alleged: Installation","index":3}}]}', slots: [ { kind: 'brand', petname: 'zoe invite' }, { kind: 'unnamed', petname: 'unnamed-4' }, @@ -505,14 +505,19 @@ test('lib-wallet dapp suggests issuer, instance, installation petnames', async t value: [ { description: 'getRefund', - handle: inviteHandle2, - instance, + + // See https://github.com/Agoric/agoric-sdk/issues/2207 + // handle: inviteHandle2, + // instance, + handle: {}, + instance: {}, + installation: {}, }, ], currentAmountSlots: { body: - '{"brand":{"@qclass":"slot","iface":"Alleged: Zoe Invitation brand","index":0},"value":[{"description":"getRefund","handle":{"@qclass":"slot","index":1},"instance":{"@qclass":"slot","index":2},"installation":{"@qclass":"slot","index":3}}]}', + '{"brand":{"@qclass":"slot","iface":"Alleged: Zoe Invitation brand","index":0},"value":[{"description":"getRefund","handle":{"@qclass":"slot","index":1},"instance":{"@qclass":"slot","iface":"Alleged: InstanceHandle","index":2},"installation":{"@qclass":"slot","iface":"Alleged: Installation","index":3}}]}', slots: [ { kind: 'brand', petname: 'zoe invite' }, { kind: 'unnamed', petname: 'unnamed-4' }, diff --git a/packages/marshal/index.js b/packages/marshal/index.js index e1e7446a14b..afe444b1c84 100644 --- a/packages/marshal/index.js +++ b/packages/marshal/index.js @@ -10,4 +10,5 @@ export { passStyleOf, makeMarshal, Remotable, + Far, } from './src/marshal'; diff --git a/packages/marshal/src/marshal.js b/packages/marshal/src/marshal.js index ab83053e38f..d07b79f984a 100644 --- a/packages/marshal/src/marshal.js +++ b/packages/marshal/src/marshal.js @@ -511,15 +511,33 @@ export function makeMarshal( slotMap.set(val, slotIndex); } - if (iface !== undefined) { + /* + if (iface === undefined && passStyleOf(val) === REMOTE_STYLE) { + // iface = `Alleged: remotable at slot ${slotIndex}`; + if ( + Object.getPrototypeOf(val) === Object.prototype && + Object.getOwnPropertyNames(val).length === 0 + ) { + // For now, skip the diagnostic if we have a pure empty object + } else { + try { + assert.fail(d`Serialize ${val} generates needs iface`); + } catch (err) { + console.info(err); + } + } + } + */ + + if (iface === undefined) { return harden({ [QCLASS]: 'slot', - iface, index: slotIndex, }); } return harden({ [QCLASS]: 'slot', + iface, index: slotIndex, }); } @@ -810,7 +828,12 @@ export function makeMarshal( * @param {InterfaceSpec} [iface='Remotable'] The interface specification for * the remotable. For now, a string iface must be "Remotable" or begin with * "Alleged: ", to serve as the alleged name. More general ifaces are not yet - * implemented. This is temporary. + * implemented. This is temporary. We include the + * "Alleged" as a reminder that we do not yet have SwingSet or Comms Vat + * support for ensuring this is according to the vat hosting the object. + * Currently, Alice can tell Bob about Carol, where VatA (on Alice's behalf) + * misrepresents Carol's `iface`. VatB and therefore Bob will then see + * Carol's `iface` as misrepresented by VatA. * @param {object} [props={}] Own-properties are copied to the remotable * @param {object} [remotable={}] The object used as the remotable * @returns {object} remotable, modified for debuggability @@ -825,7 +848,9 @@ function Remotable(iface = 'Remotable', props = {}, remotable = {}) { // TODO unimplemented assert( iface === 'Remotable' || iface.startsWith('Alleged: '), - d`For now, iface ${iface} must be "Remotable" or begin with "Alleged: "; unimplemented`, + d`For now, iface ${q( + iface, + )} must be "Remotable" or begin with "Alleged: "; unimplemented`, ); iface = pureCopy(harden(iface)); @@ -895,3 +920,17 @@ function Remotable(iface = 'Remotable', props = {}, remotable = {}) { harden(Remotable); export { Remotable }; + +/** + * A concise convenience for the most common `Remotable` use. + * + * @param {string} farName This name will be prepended with `Alleged: ` + * for now to form the `Remotable` `iface` argument. + * @param {object} [remotable={}] The object used as the remotable + * @returns {object} remotable, modified for debuggability + */ +const Far = (farName, remotable = {}) => + Remotable(`Alleged: ${farName}`, undefined, remotable); + +harden(Far); +export { Far }; diff --git a/packages/marshal/test/test-marshal.js b/packages/marshal/test/test-marshal.js index ff85315a9ee..ec4033f7140 100644 --- a/packages/marshal/test/test-marshal.js +++ b/packages/marshal/test/test-marshal.js @@ -2,6 +2,7 @@ import '@agoric/install-ses'; import test from 'ava'; import { Remotable, + Far, getInterfaceOf, makeMarshal, mustPassByPresence, @@ -197,12 +198,12 @@ test('Remotable/getInterfaceOf', t => { 'object ifaces are not implemented', ); t.throws( - () => Remotable('Alleged: MyHandle', { foo: 123 }), + () => Far('MyHandle', { foo: 123 }), { message: /cannot serialize/ }, 'non-function props are not implemented', ); t.throws( - () => Remotable('Alleged: MyHandle', {}, a => a + 1), + () => Far('MyHandle', a => a + 1), { message: /cannot serialize/ }, 'function presences are not implemented', ); @@ -217,13 +218,13 @@ test('Remotable/getInterfaceOf', t => { t.is(getInterfaceOf(123), undefined, 'number, no interface'); // Check that a handle can be created. - const p = Remotable('Alleged: MyHandle'); + const p = Far('MyHandle'); harden(p); // console.log(p); t.is(getInterfaceOf(p), 'Alleged: MyHandle', `interface is MyHandle`); t.is(`${p}`, '[Alleged: MyHandle]', 'stringify is [MyHandle]'); - const p2 = Remotable('Alleged: Thing', { + const p2 = Far('Thing', { name() { return 'cretin'; }, diff --git a/packages/swingset-runner/demo/vatResolveTest/bootstrap.js b/packages/swingset-runner/demo/vatResolveTest/bootstrap.js index d9e24b43372..bde8e653daf 100644 --- a/packages/swingset-runner/demo/vatResolveTest/bootstrap.js +++ b/packages/swingset-runner/demo/vatResolveTest/bootstrap.js @@ -1,11 +1,12 @@ import { E } from '@agoric/eventual-send'; +import { Far } from '@agoric/marshal'; const log = console.log; log(`=> loading bootstrap.js`); export function buildRootObject(_vatPowers) { - const target1 = { + const target1 = Far('target1', { one(_p) { log(`target1 in one`); }, @@ -18,8 +19,8 @@ export function buildRootObject(_vatPowers) { four() { log(`target1 in four`); }, - }; - const target2 = { + }); + const target2 = Far('target2', { one(_p) { log(`target2 in one`); }, @@ -32,7 +33,7 @@ export function buildRootObject(_vatPowers) { four() { log(`target2 in four`); }, - }; + }); return harden({ bootstrap(vats) { const bob = vats.bob; diff --git a/packages/swingset-runner/package.json b/packages/swingset-runner/package.json index 6028ef4c876..bff6af9c416 100644 --- a/packages/swingset-runner/package.json +++ b/packages/swingset-runner/package.json @@ -23,6 +23,7 @@ "@agoric/ertp": "^0.9.0", "@agoric/eventual-send": "^0.13.0", "@agoric/install-ses": "^0.5.0", + "@agoric/marshal": "^0.3.0", "@agoric/same-structure": "^0.1.0", "@agoric/stat-logger": "^0.4.0", "@agoric/swing-store-lmdb": "^0.4.0", diff --git a/packages/zoe/src/contractFacet/contractFacet.js b/packages/zoe/src/contractFacet/contractFacet.js index f0bed9b9699..2908fb73b3c 100644 --- a/packages/zoe/src/contractFacet/contractFacet.js +++ b/packages/zoe/src/contractFacet/contractFacet.js @@ -362,7 +362,7 @@ export function buildRootObject(powers, _params, testJigSetter = undefined) { details`invitations must have a description string: ${description}`, ); - const invitationHandle = /** @type {InvitationHandle} */ (harden({})); + const invitationHandle = makeHandle('Invitation'); invitationHandleToHandler.init(invitationHandle, offerHandler); /** @type {Promise} */ const invitationP = E(zoeInstanceAdmin).makeInvitation( diff --git a/packages/zoe/src/contractFacet/seat.js b/packages/zoe/src/contractFacet/seat.js index 34c3e48e279..8de9568be15 100644 --- a/packages/zoe/src/contractFacet/seat.js +++ b/packages/zoe/src/contractFacet/seat.js @@ -2,6 +2,7 @@ import { E } from '@agoric/eventual-send'; import { assert, details } from '@agoric/assert'; +import { Far } from '@agoric/marshal'; import { isOfferSafe } from './offerSafety'; @@ -44,7 +45,7 @@ export const makeZcfSeatAdminKit = ( }); /** @type {ZCFSeat} */ - const zcfSeat = harden({ + const zcfSeat = Far('zcfSeat', { exit: completion => { assertExitedFalse(); zcfSeatAdmin.updateHasExited(); diff --git a/packages/zoe/src/makeHandle.js b/packages/zoe/src/makeHandle.js index 0a14e4e692e..140d3035929 100644 --- a/packages/zoe/src/makeHandle.js +++ b/packages/zoe/src/makeHandle.js @@ -1,4 +1,5 @@ import { assert } from '@agoric/assert'; +import { Far } from '@agoric/marshal'; /** * Create an opaque handle object. @@ -11,5 +12,5 @@ export const makeHandle = handleType => { // This assert ensures that handleType is referenced. assert.typeof(handleType, 'string', 'handleType must be a string'); // Return the intersection type (really just an empty object). - return /** @type {Handle} */ (harden({})); + return /** @type {Handle} */ (Far(`${handleType}Handle`)); }; diff --git a/packages/zoe/src/types.js b/packages/zoe/src/types.js index 8ceede2a2ba..e52995fa498 100644 --- a/packages/zoe/src/types.js +++ b/packages/zoe/src/types.js @@ -12,7 +12,7 @@ /** * @typedef {string} Keyword - * @typedef {Handle<'InvitationHandle'>} InvitationHandle - an opaque handle for an invitation + * @typedef {Handle<'Invitation'>} InvitationHandle - an opaque handle for an invitation * @typedef {Record} IssuerKeywordRecord * @typedef {Record} BrandKeywordRecord */ diff --git a/packages/zoe/src/zoeService/types.js b/packages/zoe/src/zoeService/types.js index 0fd3eed92c2..136730a509b 100644 --- a/packages/zoe/src/zoeService/types.js +++ b/packages/zoe/src/zoeService/types.js @@ -172,7 +172,7 @@ */ /** - * @typedef {Handle<'InstanceHandle'>} Instance + * @typedef {Handle<'Instance'>} Instance */ /** diff --git a/packages/zoe/src/zoeService/zoe.js b/packages/zoe/src/zoeService/zoe.js index 206652897e0..f6ac251b7d7 100644 --- a/packages/zoe/src/zoeService/zoe.js +++ b/packages/zoe/src/zoeService/zoe.js @@ -14,6 +14,7 @@ import { makeIssuerKit, MathKind } from '@agoric/ertp'; import '../../exported'; import '../internal-types'; +import { Far } from '@agoric/marshal'; import { makeIssuerTable } from '../issuerTable'; import { makeZoeSeatAdminKit } from './zoeSeat'; import zcfContractBundle from '../../bundles/bundle-contractFacet'; @@ -57,7 +58,9 @@ function makeZoe(vatAdminSvc, zcfBundleName = undefined) { const install = async bundle => { assert(bundle, `a bundle must be provided`); /** @type {Installation} */ - const installation = { getBundle: () => bundle }; + const installation = Far('Installation', { + getBundle: () => bundle, + }); harden(installation); installations.add(installation); return installation; @@ -73,7 +76,7 @@ function makeZoe(vatAdminSvc, zcfBundleName = undefined) { }; /** @type {ZoeService} */ - const zoeService = { + const zoeService = Far('zoeService', { getInvitationIssuer: () => invitationKit.issuer, install, getPublicFacet: instance => @@ -108,7 +111,7 @@ function makeZoe(vatAdminSvc, zcfBundleName = undefined) { details`${installation} was not a valid installation`, ); - const instance = makeHandle('InstanceHandle'); + const instance = makeHandle('Instance'); const keywords = cleanKeywords(uncleanIssuerKeywordRecord); @@ -233,7 +236,7 @@ function makeZoe(vatAdminSvc, zcfBundleName = undefined) { let acceptingOffers = true; /** @type {InstanceAdmin} */ - return { + return Far('instanceAdmin', { addZoeSeatAdmin: zoeSeatAdmin => zoeSeatAdmins.add(zoeSeatAdmin), tellZCFToMakeSeat: ( invitationHandle, @@ -265,7 +268,7 @@ function makeZoe(vatAdminSvc, zcfBundleName = undefined) { zoeSeatAdmins.forEach(zoeSeatAdmin => zoeSeatAdmin.fail(reason)); }, stopAcceptingOffers: () => (acceptingOffers = false), - }; + }); }; const instanceAdmin = makeInstanceAdmin(); @@ -286,7 +289,7 @@ function makeZoe(vatAdminSvc, zcfBundleName = undefined) { } = invitationKit; /** @type {ZoeInstanceAdmin} */ - const zoeInstanceAdminForZcf = { + const zoeInstanceAdminForZcf = Far('zoeInstanceAdminForZcf', { makeInvitation: (invitationHandle, description, customProperties) => { const invitationAmount = invitationAmountMath.make( harden([ @@ -339,7 +342,7 @@ function makeZoe(vatAdminSvc, zcfBundleName = undefined) { }); }, stopAcceptingOffers: () => instanceAdmin.stopAcceptingOffers(), - }; + }); // At this point, the contract will start executing. All must be // ready @@ -488,7 +491,7 @@ function makeZoe(vatAdminSvc, zcfBundleName = undefined) { }, ); }, - }; + }); harden(zoeService); return zoeService; diff --git a/packages/zoe/src/zoeService/zoeSeat.js b/packages/zoe/src/zoeService/zoeSeat.js index 9d10a536a5c..2fd2ca4506b 100644 --- a/packages/zoe/src/zoeService/zoeSeat.js +++ b/packages/zoe/src/zoeService/zoeSeat.js @@ -4,6 +4,7 @@ import { makePromiseKit } from '@agoric/promise-kit'; import { makeNotifierKit } from '@agoric/notifier'; import { assert } from '@agoric/assert'; import { E } from '@agoric/eventual-send'; +import { Far } from '@agoric/marshal'; import { objectMap } from '../objArrayConversion'; import '../types'; @@ -51,7 +52,7 @@ export const makeZoeSeatAdminKit = ( }; /** @type {ZoeSeatAdmin} */ - const zoeSeatAdmin = harden({ + const zoeSeatAdmin = Far('zoeSeatAdmin', { replaceAllocation: replacementAllocation => { assert( instanceAdmin.hasZoeSeatAdmin(zoeSeatAdmin), @@ -83,7 +84,7 @@ export const makeZoeSeatAdminKit = ( }); /** @type {UserSeat} */ - const userSeat = harden({ + const userSeat = Far('userSeat', { getCurrentAllocation: async () => zoeSeatAdmin.getCurrentAllocation(), getProposal: async () => proposal, getPayouts: async () => payoutPromiseKit.promise, diff --git a/packages/zoe/test/unitTests/contractSupport/test-zoeHelpers.js b/packages/zoe/test/unitTests/contractSupport/test-zoeHelpers.js index 989e130a120..8bac1a27b32 100644 --- a/packages/zoe/test/unitTests/contractSupport/test-zoeHelpers.js +++ b/packages/zoe/test/unitTests/contractSupport/test-zoeHelpers.js @@ -2,6 +2,7 @@ import '@agoric/install-ses'; // eslint-disable-next-line import/no-extraneous-dependencies import test from 'ava'; +import { Far } from '@agoric/marshal'; import makeStore from '@agoric/store'; import { setup } from '../setupBasicMints'; @@ -45,7 +46,7 @@ function makeMockTradingZcfBuilder() { test('ZoeHelpers satisfies blank proposal', t => { const { moolaR, moola } = setup(); - const fakeZcfSeat = harden({ + const fakeZcfSeat = Far('fakeZcfSeat', { getCurrentAllocation: () => harden({ Asset: moola(10) }), getProposal: () => harden({}), }); @@ -60,7 +61,7 @@ test('ZoeHelpers satisfies blank proposal', t => { test('ZoeHelpers satisfies simple proposal', t => { const { moolaR, moola, simoleans } = setup(); - const fakeZcfSeat = harden({ + const fakeZcfSeat = Far('fakeZcfSeat', { getCurrentAllocation: () => harden({ Asset: moola(10) }), getProposal: () => harden({ want: { Desire: moola(30) } }), }); @@ -91,7 +92,7 @@ test('ZoeHelpers satisfies simple proposal', t => { test('ZoeHelpers satisfies() with give', t => { const { moolaR, moola, bucks, bucksR, simoleanR } = setup(); - const fakeZcfSeat = harden({ + const fakeZcfSeat = Far('fakeZcfSeat', { getCurrentAllocation: () => harden({ Charge: moola(30) }), getProposal: () => harden({ give: { Charge: moola(30) }, want: { Desire: bucks(5) } }), @@ -129,7 +130,7 @@ const makeMockZcfSeatAdmin = (proposal, initialAllocation, getAmountMath) => { getAmountMath, ); let hasExited = false; - const mockSeat = harden({ + const mockSeat = Far('mockSeat', { isOfferSafe: actual.isOfferSafe, getCurrentAllocation: actual.getCurrentAllocation, getProposal: () => proposal,