Skip to content

Commit

Permalink
chore(bootstrap): make the bridge handler for provisioning durable
Browse files Browse the repository at this point in the history
Refs: #10425
  • Loading branch information
anilhelvaci committed Nov 18, 2024
1 parent 0fa2d27 commit 6be81d7
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 53 deletions.
51 changes: 38 additions & 13 deletions packages/boot/test/bootstrapTests/vaults-upgrade.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,19 @@ test.serial('re-bootstrap', async t => {
test.serial('audit bootstrap exports', async t => {
const expected = {
maxExports: 5,
maxNonDurable: 5,
maxNonDurable: 4,
ifaces: {
// in bridgeCoreEval()
coreHandler: true,
// in bridgeProvisioner()
provisioningHandler: true,
'prioritySenders manager': true,
// TODO? move to provisioning vat?
clientCreator: true,
durable: {
// in bridgeProvisioner()
provisioningHandler: true,
},
nonDurable: {
// in bridgeCoreEval()
coreHandler: true,
'prioritySenders manager': true,
// TODO? move to provisioning vat?
clientCreator: true,
},
},
};

Expand Down Expand Up @@ -221,24 +225,45 @@ test.serial('audit bootstrap exports', async t => {
const { methargs } = sc.s[2];
if (!methargs.slots.includes(oid)) continue;
m.fromCapData(methargs);
return;
break;
} else if (sc.s[0] === 'resolve') {
for (const res of sc.s[1]) {
const capdata = res[2];
if (!capdata.slots.includes(oid)) continue;
m.fromCapData(capdata);
return;
break;
}
}
}
}
}

const exportedInterfaces = Object.fromEntries(
[...toIface.values()].map(iface => [iface.replace(/^Alleged: /, ''), true]),
const exportedInterfacesNonDurable = Object.fromEntries(
[...toIface.entries()]
.filter(([slot, _]) => !slot.startsWith('o+d'))
.map(([_, iface]) => [iface.replace(/^Alleged: /, ''), true]),
);

t.deepEqual(exportedInterfaces, expected.ifaces, 'expected interfaces');
const exportedInterfacesDurable = Object.fromEntries(
[...toIface.entries()]
.filter(([slot, _]) => slot.startsWith('o+d'))
.map(([_, iface]) => [iface.replace(/^Alleged: /, ''), true]),
);

t.deepEqual(
exportedInterfacesNonDurable,
expected.ifaces.nonDurable,
'expected non-durable interfaces',
);
t.deepEqual(
exportedInterfacesDurable,
expected.ifaces.durable,
'expected durable interfaces',
);
t.true(
oids.size - oidsDurable.length <= expected.maxNonDurable,
'too many non-durable',
);
});

test.serial('open vault', async t => {
Expand Down
66 changes: 26 additions & 40 deletions packages/vats/src/core/chain-behaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import {
} from '@agoric/notifier';
import { makeScalarBigMapStore } from '@agoric/vat-data';
import { prepareRecorderKit } from '@agoric/zoe/src/contractSupport/recorder.js';
import { PowerFlags } from '../walletFlags.js';
import { BASIC_BOOTSTRAP_PERMITS } from './basic-behaviors.js';
import { agoricNamesReserved, callProperties, extractPowers } from './utils.js';
import { makeScopedBridge } from '../bridge.js';
import { prepareProvisionBridgeHandler } from '../lib-provisioning.js';

const { keys } = Object;

Expand Down Expand Up @@ -136,53 +136,35 @@ export const bridgeProvisioner = async ({
provisioning: provisioningP,
provisionBridgeManager: provisionBridgeManagerP,
provisionWalletBridgeManager: provisionWalletBridgeManagerP,
powerStore: powerStoreP,
},
}) => {
const [provisioning, provisionBridgeManager, provisionWalletBridgeManager] =
await Promise.all([
provisioningP,
provisionBridgeManagerP,
provisionWalletBridgeManagerP,
]);
const [
provisioning,
provisionBridgeManager,
provisionWalletBridgeManager,
powerStore,
] = await Promise.all([
provisioningP,
provisionBridgeManagerP,
provisionWalletBridgeManagerP,
powerStoreP,
]);
if (!provisionBridgeManager || !provisionWalletBridgeManager) {
return;
}

// const baggage = makeScalarBigMapStore('provisionBridgeHandlerBaggage', { durable: true });
// produceProvisioningHandlerBaggage.resolve(baggage);
const makeProvisionBridgeHandler = prepareProvisionBridgeHandler(powerStore);
const provisioningHandler = makeProvisionBridgeHandler(
provisioning,
provisionWalletBridgeManager,
);

// Register a provisioning handler over the bridge.
const handler = provisioning
? Far('provisioningHandler', {
async fromBridge(obj) {
switch (obj.type) {
case 'PLEASE_PROVISION': {
const { nickname, address, powerFlags: rawPowerFlags } = obj;
const powerFlags = rawPowerFlags || [];
let provisionP;
if (powerFlags.includes(PowerFlags.SMART_WALLET)) {
// Only provision a smart wallet.
provisionP = E(provisionWalletBridgeManager).fromBridge(obj);
} else {
// Provision a mailbox and REPL.
provisionP = E(provisioning).pleaseProvision(
nickname,
address,
powerFlags,
);
}
return provisionP
.catch(e =>
console.error(
`Error provisioning ${nickname} ${address}:`,
e,
),
)
.then(_ => {});
}
default: {
throw Fail`Unrecognized request ${obj.type}`;
}
}
},
})
? provisioningHandler
: provisionWalletBridgeManager;
await E(provisionBridgeManager).initHandler(handler);
};
Expand Down Expand Up @@ -557,6 +539,10 @@ export const SHARED_CHAIN_BOOTSTRAP_MANIFEST = {
bridgeManager: 'bridge',
provisionBridgeManager: 'bridge',
provisionWalletBridgeManager: 'bridge',
powerStore: 'bridge',
},
produce: {
provisioningHandlerBaggage: true,
},
},
[setupClientManager.name]: {
Expand Down
53 changes: 53 additions & 0 deletions packages/vats/src/lib-provisioning.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { prepareExoClass } from '@agoric/vat-data';
import { Fail } from '@endo/errors';
import { E } from '@endo/far';
import { BridgeHandlerI } from './bridge.js';
import { PowerFlags } from './walletFlags.js';

/**
* @param {import('@agoric/store').MapStore} baggage
*/
export const prepareProvisionBridgeHandler = baggage => {
const makeProvisionBridgeHandler = prepareExoClass(
baggage,
'provisioningHandler',
BridgeHandlerI,
(provisioning, provisionWalletBridgeManager) => ({
provisioning,
provisionWalletBridgeManager,
}),
{
async fromBridge(obj) {
const { provisionWalletBridgeManager, provisioning } = this.state;
switch (obj.type) {
case 'PLEASE_PROVISION': {
const { nickname, address, powerFlags: rawPowerFlags } = obj;
const powerFlags = rawPowerFlags || [];
let provisionP;
if (powerFlags.includes(PowerFlags.SMART_WALLET)) {
// Only provision a smart wallet.
provisionP = E(provisionWalletBridgeManager).fromBridge(obj);
} else {
// Provision a mailbox and REPL.
provisionP = E(provisioning).pleaseProvision(
nickname,
address,
powerFlags,
);
}
return provisionP
.catch(e =>
console.error(`Error provisioning ${nickname} ${address}:`, e),
)
.then(_ => {});
}
default: {
throw Fail`Unrecognized request ${obj.type}`;
}
}
},
},
);

return makeProvisionBridgeHandler;
};

0 comments on commit 6be81d7

Please sign in to comment.