Skip to content

Commit

Permalink
chore: durable bridgeHandler
Browse files Browse the repository at this point in the history
Refs: #10425
Refs: #10564
  • Loading branch information
anilhelvaci committed Nov 25, 2024
1 parent 6fdcf87 commit 1e8f8d0
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 45 deletions.
11 changes: 9 additions & 2 deletions packages/inter-protocol/src/provisionPool.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,16 @@ import { prepareExo } from '@agoric/vat-data';
import { provideSingleton } from '@agoric/zoe/src/contractSupport/durability.js';
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js';
import { TopicsRecordShape } from '@agoric/zoe/src/contractSupport/topics.js';
import { prepareProvisionPoolKit } from './provisionPoolKit.js';
import { makeDurableZone } from '@agoric/zone/durable.js';
import { makeTracer } from '@agoric/internal';
import {
prepareProvisionPoolKit,
} from './provisionPoolKit.js';

/** @import {Marshal} from '@endo/marshal'; */

const tracer = makeTracer('DEBUG_PP');

/** @type {ContractMeta} */
export const meta = {
privateArgsShape: M.splitRecord(
Expand Down Expand Up @@ -72,7 +78,8 @@ export const start = async (zcf, privateArgs, baggage) => {
privateArgs.marshaller,
);

const makeProvisionPoolKit = prepareProvisionPoolKit(baggage, {
const zone = makeDurableZone(baggage);
const makeProvisionPoolKit = prepareProvisionPoolKit(zone, {
makeRecorderKit,
params,
poolBank,
Expand Down
101 changes: 67 additions & 34 deletions packages/inter-protocol/src/provisionPoolKit.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// @ts-check
import { X, q, Fail } from '@endo/errors';
import { E } from '@endo/far';
import { Far } from '@endo/marshal';
import { E, Far } from '@endo/far';

import { AmountMath, BrandShape } from '@agoric/ertp';
import { deeplyFulfilledObject, makeTracer } from '@agoric/internal';
Expand All @@ -15,7 +14,6 @@ import {
M,
makeScalarBigMapStore,
makeScalarBigSetStore,
prepareExoClassKit,
} from '@agoric/vat-data';
import { PowerFlags } from '@agoric/vats/src/walletFlags.js';
import {
Expand Down Expand Up @@ -66,17 +64,16 @@ const FIRST_LOWER_NEAR_KEYWORD = /^[a-z][a-zA-Z0-9_$]*$/;
* Given attenuated access to the funding purse, handle requests to provision
* smart wallets.
*
* @param {(depositBank: ERef<Bank>) => Promise<void>} sendInitialPayment
* @param {() => void} onProvisioned
* @param {import('@agoric/zone').Zone} zone
* @param helpers
*/
export const makeBridgeProvisionTool = (sendInitialPayment, onProvisioned) => {
/** @param {ProvisionPoolKitReferences} refs */
const makeBridgeHandler = ({
bankManager,
namesByAddressAdmin,
walletFactory,
}) =>
Far('provisioningHandler', {
export const prepareBridgeProvisionTool = (zone, helpers) =>
zone.exo(
'smartWalletProvisioningHandler',
M.interface('ProvisionBridgeHandlerMaker', {
fromBridge: M.callWhen(M.record()).returns(),
}),
{
fromBridge: async obj => {
obj.type === 'PLEASE_PROVISION' ||
Fail`Unrecognized request ${obj.type}`;
Expand All @@ -85,26 +82,30 @@ export const makeBridgeProvisionTool = (sendInitialPayment, onProvisioned) => {
powerFlags.includes(PowerFlags.SMART_WALLET) ||
Fail`missing SMART_WALLET in powerFlags`;

const { bankManager, walletFactory, namesByAddressAdmin } =
await E(helpers).getReferences();

trace({ bankManager, walletFactory, namesByAddressAdmin });

const bank = E(bankManager).getBankForAddress(address);
// only proceed if we can provide funds
await sendInitialPayment(bank);
await E(helpers).sendInitialPayment(bank);

const [_, created] = await E(walletFactory).provideSmartWallet(
address,
bank,
namesByAddressAdmin,
);
if (created) {
onProvisioned();
E(helpers).onProvisioned();
}
trace(created ? 'provisioned' : 're-provisioned', address);
},
});
return makeBridgeHandler;
};
},
);

/**
* @param {import('@agoric/vat-data').Baggage} baggage
* @param {import('@agoric/zone').Zone} zone
* @param {{
* makeRecorderKit: import('@agoric/zoe/src/contractSupport/recorder.js').MakeRecorderKit;
* params: any;
Expand All @@ -113,13 +114,12 @@ export const makeBridgeProvisionTool = (sendInitialPayment, onProvisioned) => {
* }} powers
*/
export const prepareProvisionPoolKit = (
baggage,
zone,
{ makeRecorderKit, params, poolBank, zcf },
) => {
const zoe = zcf.getZoeService();

const makeProvisionPoolKitInternal = prepareExoClassKit(
baggage,
const makeProvisionPoolKitInternal = zone.exoClassKit(
'ProvisionPoolKit',
{
machine: M.interface('ProvisionPoolKit machine', {
Expand All @@ -132,7 +132,12 @@ export const prepareProvisionPoolKit = (
namesByAddressAdmin: M.eref(M.remotable('nameAdmin')),
walletFactory: M.eref(M.remotable('walletFactory')),
}).returns(),
makeHandler: M.call().returns(M.remotable('BridgeHandler')),
makeHandler: M.callWhen().returns(M.remotable('handler')),
getReferences: M.call().returns({
bankManager: M.eref(M.remotable()),
namesByAddressAdmin: M.eref(M.remotable('nameAdmin')),
walletFactory: M.eref(M.remotable('walletFactory')),
}),
initPSM: M.call(BrandShape, InstanceHandleShape).returns(),
}),
walletReviver: M.interface('ProvisionPoolKit wallet reviver', {
Expand Down Expand Up @@ -183,6 +188,7 @@ export const prepareProvisionPoolKit = (
totalMintedProvided: AmountMath.makeEmpty(poolBrand),
totalMintedConverted: AmountMath.makeEmpty(poolBrand),
revivableAddresses,
provisionHandler: undefined,
...references,
};
},
Expand All @@ -208,23 +214,34 @@ export const prepareProvisionPoolKit = (
const refs = await deeplyFulfilledObject(obj);
Object.assign(this.state, refs);
},
makeHandler() {
const { bankManager, namesByAddressAdmin, walletFactory } =
getReferences() {
const { bankManager, walletFactory, namesByAddressAdmin } =
this.state;
return harden({ bankManager, walletFactory, namesByAddressAdmin });
},
/** @returns {import('@agoric/vats').BridgeHandler} */
makeHandler() {
const {
bankManager,
namesByAddressAdmin,
walletFactory,
provisionHandler,
} = this.state;
if (!bankManager || !namesByAddressAdmin || !walletFactory) {
throw Fail`must set references before handling requests`;
}
const { helper } = this.facets;
// a bit obtuse but leave for backwards compatibility with tests
const innerMaker = makeBridgeProvisionTool(
bank => helper.sendInitialPayment(bank),
() => helper.onProvisioned(),
);
return innerMaker({

if (!provisionHandler) {
throw Fail`provisionHandler not created`;
}
trace({
bankManager,
namesByAddressAdmin,
walletFactory,
provisionHandler,
});

return provisionHandler;
},
/**
* @param {Brand} brand
Expand Down Expand Up @@ -494,8 +511,23 @@ export const prepareProvisionPoolKit = (
},
},
{
finish: ({ facets }) => {
facets.helper.publishMetrics();
finish: ({ facets, state }) => {
const { helper, machine } = facets;
helper.publishMetrics();
const handlerZone = zone.subZone('HandlerZone'); // see what options are available
// use provide here maybe?
const provisionHandler = prepareBridgeProvisionTool(
handlerZone,
Far('Helpers', {
sendInitialPayment: bank => helper.sendInitialPayment(bank),
onProvisioned: () => helper.onProvisioned(),
getReferences: () => machine.getReferences(),
}),
);

trace('PROVISION_HANDLER', provisionHandler);

Object.assign(state, { provisionHandler });
},
},
);
Expand All @@ -506,6 +538,7 @@ export const prepareProvisionPoolKit = (
* @param {object} opts
* @param {Brand<'nat'>} opts.poolBrand
* @param {ERef<StorageNode>} opts.storageNode
* @param {ERef<any>} opts.bridgeHandlerKit
*/
const makeProvisionPoolKit = async ({ poolBrand, storageNode }) => {
const fundPurse = await E(poolBank).getPurse(poolBrand);
Expand Down
24 changes: 15 additions & 9 deletions packages/inter-protocol/test/provisionPool.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import { makeFakeBoard } from '@agoric/vats/tools/board-utils.js';
import { makeRatio } from '@agoric/zoe/src/contractSupport/ratio.js';
import { E, Far } from '@endo/far';
import path from 'path';
import { makeBridgeProvisionTool } from '../src/provisionPoolKit.js';
import { makeHeapZone } from '@agoric/zone';
import { prepareBridgeProvisionTool } from '../src/provisionPoolKit.js';
import {
makeMockChainStorageRoot,
setUpZoeForTest,
Expand Down Expand Up @@ -364,15 +365,20 @@ test('makeBridgeProvisionTool handles duplicate requests', async t => {
const { nameHub: namesByAddress, nameAdmin: namesByAddressAdmin } =
makeNameHubKit();
const publishMetrics = () => {};
const makeHandler = makeBridgeProvisionTool(
sendInitialPayment,
publishMetrics,
const zone = makeHeapZone();
const handler = prepareBridgeProvisionTool(
zone,
Far('helper', {
sendInitialPayment,
onProvisioned: () => publishMetrics(),
getReferences: () =>
harden({
bankManager,
namesByAddressAdmin,
walletFactory,
}),
}),
);
const handler = makeHandler({
bankManager,
namesByAddressAdmin,
walletFactory,
});

t.log('1st request to provision a SMART_WALLET for', address);
await handler.fromBridge({
Expand Down

0 comments on commit 1e8f8d0

Please sign in to comment.