Skip to content

Commit

Permalink
refactor(vats): separate core behaviors, manifests, and other parts
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Jan 26, 2022
1 parent 116ccbd commit e1bb213
Show file tree
Hide file tree
Showing 9 changed files with 593 additions and 553 deletions.
89 changes: 1 addition & 88 deletions packages/vats/decentral-core-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,94 +2,7 @@
"bootstrap": "bootstrap",
"vats": {
"bootstrap": {
"sourceSpec": "./src/core/boot.js",
"parameters": {
"bootstrapManifest": {
"connectVattpWithMailbox": {
"vatPowers": {
"D": true
},
"vats": {
"vattp": true
},
"devices": {
"mailbox": true
}
},
"makeVatsFromBundles": {
"vats": {
"vatAdmin": true
},
"devices": {
"vatAdmin": true
},
"produce": {
"vatAdminSvc": true,
"loadVat": true
}
},
"buildZoe": {
"consume": {
"agoricNames": true,
"nameAdmins": true,
"vatAdminSvc": true,
"loadVat": true,
"client": true
},
"produce": {
"zoe": true,
"feeMintAccess": true
}
},
"makeBoard": {
"consume": {
"loadVat": true,
"client": true
},
"produce": {
"board": true
}
},
"makeAddressNameHubs": {
"consume": {
"client": true
},
"produce": {
"agoricNames": true,
"agoricNamesAdmin": true,
"nameAdmins": true
}
},
"startTimerService": {
"devices": {
"timer": true
},
"vats": {
"timer": true
},
"produce": {
"chainTimerService": true
}
},
"makeClientBanks": {
"consume": {
"loadVat": true,
"client": true,
"bridgeManager": true
},
"produce": {
"bankManager": true
}
},
"makeBLDKit": {
"consume": {
"agoricNames": true,
"bankManager": true,
"nameAdmins": true
}
}
}
}
"sourceSpec": "./src/core/boot.js"
}
},
"bundles": {
Expand Down
280 changes: 280 additions & 0 deletions packages/vats/src/core/basic-behaviors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
// @ts-check
import { E, Far } from '@agoric/far';
import { makeIssuerKit } from '@agoric/ertp';

import { makeStore } from '@agoric/store';
import { makeNameHubKit } from '../nameHub.js';
import { BLD_ISSUER_ENTRY } from '../issuers.js';

import { feeIssuerConfig, collectNameAdmins, shared } from './utils';

const { keys } = Object;

/**
* TODO: review behaviors carefully for powers that go out of scope,
* since we may want/need them later.
*/

/**
* @param {{
* vatPowers: { D: EProxy }, // D type is approximate
* vats: { vattp: VattpVat },
* devices: { mailbox: MailboxDevice },
* }} powers
*/
export const connectVattpWithMailbox = ({
vatPowers: { D },
vats: { vattp },
devices: { mailbox },
}) => {
D(mailbox).registerInboundHandler(vattp);
return E(vattp).registerMailboxDevice(mailbox);
};
harden(connectVattpWithMailbox);

/**
* @param {{
* vats: { vatAdmin: VatAdminVat },
* devices: { vatAdmin: unknown },
* produce: {
* vatAdminSvc: Producer<ERef<VatAdminSvc>>,
* loadVat: Producer<VatLoader<unknown>>,
* },
* }} powers
*/
export const makeVatsFromBundles = ({
vats,
devices,
produce: { vatAdminSvc, loadVat },
}) => {
const svc = E(vats.vatAdmin).createVatAdminService(devices.vatAdmin);
vatAdminSvc.resolve(svc);
// TODO: getVat? do we need to memoize this by name?
// TODO: rename loadVat to createVatByName?
loadVat.resolve(bundleName => {
console.info(`createVatByName(${bundleName})`);
const root = E(svc)
.createVatByName(bundleName)
.then(r => r.root);
return root;
});
};
harden(makeVatsFromBundles);

/**
* @param {{
* consume: {
* agoricNames: ERef<NameHub>,
* vatAdminSvc: ERef<VatAdminSvc>,
* loadVat: ERef<VatLoader<ZoeVat>>,
* nameAdmins: ERef<Store<NameHub, NameAdmin>>,
* client: ERef<ClientConfig>
* },
* produce: { zoe: Producer<ZoeService>, feeMintAccess: Producer<FeeMintAccess> },
* }} powers
*
* @typedef {ERef<ReturnType<import('../vat-zoe.js').buildRootObject>>} ZoeVat
*/
export const buildZoe = async ({
consume: { agoricNames, vatAdminSvc, loadVat, client, nameAdmins },
produce: { zoe, feeMintAccess },
}) => {
const { zoeService, feeMintAccess: fma } = await E(
E(loadVat)('zoe'),
).buildZoe(vatAdminSvc, feeIssuerConfig);

zoe.resolve(zoeService);

const runIssuer = await E(zoeService).getFeeIssuer();
const runBrand = await E(runIssuer).getBrand();
const [issuerAdmin, brandAdmin] = await collectNameAdmins(
['issuer', 'brand'],
agoricNames,
nameAdmins,
);

feeMintAccess.resolve(fma);
return Promise.all([
E(issuerAdmin).update('RUN', runIssuer),
E(brandAdmin).update('RUN', runBrand),
E(client).assignBundle({ zoe: _addr => zoeService }),
]);
};
harden(buildZoe);

/**
* TODO: rename this to getBoard?
*
* @param {{
* consume: { loadVat: ERef<VatLoader<BoardVat>>, client: ERef<ClientConfig> },
* produce: { board: Producer<ERef<Board>> },
* }} powers
* @typedef {ERef<ReturnType<import('../vat-board.js').buildRootObject>>} BoardVat
*/
export const makeBoard = async ({
consume: { loadVat, client },
produce: {
board: { resolve: resolveBoard },
},
}) => {
const board = E(E(loadVat)('board')).getBoard();
resolveBoard(board);
return E(client).assignBundle({ board: _addr => board });
};
harden(makeBoard);

/**
* @param {{
* consume: { client: ERef<ClientConfig> },
* produce: {
* agoricNames: Producer<NameHub>,
* agoricNamesAdmin: Producer<NameAdmin>,
* nameAdmins: Producer<Store<NameHub, NameAdmin>>,
* },
* }} powers
*/
export const makeAddressNameHubs = async ({ consume: { client }, produce }) => {
const {
nameHub: agoricNames,
nameAdmin: agoricNamesAdmin,
} = makeNameHubKit();
produce.agoricNames.resolve(agoricNames);
produce.agoricNamesAdmin.resolve(agoricNamesAdmin);

const {
nameHub: namesByAddress,
nameAdmin: namesByAddressAdmin,
} = makeNameHubKit();

/** @type {Store<NameHub, NameAdmin>} */
const nameAdmins = makeStore('nameHub');
await Promise.all(
['brand', 'installation', 'issuer', 'instance', 'uiConfig'].map(
async nm => {
const { nameHub, nameAdmin } = makeNameHubKit();
await E(agoricNamesAdmin).update(nm, nameHub);
nameAdmins.init(nameHub, nameAdmin);
if (nm === 'uiConfig') {
// Reserve the Vault Factory's config until we've populated it.
nameAdmin.reserve('vaultFactory');
} else if (['issuer', 'brand'].includes(nm)) {
keys(shared.assets).forEach(k => nameAdmin.reserve(k));
} else if (['installation', 'instance'].includes(nm)) {
keys(shared.contract).forEach(k => nameAdmin.reserve(k));
}
},
),
);
produce.nameAdmins.resolve(nameAdmins);

const perAddress = address => {
// Create a name hub for this address.
const {
nameHub: myAddressNameHub,
nameAdmin: rawMyAddressNameAdmin,
} = makeNameHubKit();
// Register it with the namesByAddress hub.
namesByAddressAdmin.update(address, myAddressNameHub);

/** @type {MyAddressNameAdmin} */
const myAddressNameAdmin = Far('myAddressNameAdmin', {
...rawMyAddressNameAdmin,
getMyAddress: () => address,
});
return myAddressNameAdmin;
};

return E(client).assignBundle({
agoricNames: _ => agoricNames,
namesByAddress: _ => namesByAddress,
myAddressNameAdmin: perAddress,
});
};
harden(makeAddressNameHubs);

/**
* @param {{
* consume: {
* loadVat: ERef<VatLoader<BankVat>>,
* client: ERef<ClientConfig>,
* bridgeManager: import('../bridge.js').BridgeManager,
* },
* produce: { bankManager: Producer<unknown> },
* }} powers
* @typedef {ERef<ReturnType<import('../vat-bank.js').buildRootObject>>} BankVat
*/
export const makeClientBanks = async ({
consume: { loadVat, client, bridgeManager },
produce: { bankManager },
}) => {
const settledBridge = await bridgeManager; // ISSUE: why await? it's remote, no?
const mgr = E(E(loadVat)('bank')).makeBankManager(settledBridge);
bankManager.resolve(mgr);
return E(client).assignBundle({
bank: address => E(mgr).getBankForAddress(address),
});
};
harden(makeClientBanks);

/**
* @param {{
* consume: {
* agoricNames: Promise<NameHub>,
* bankManager: Promise<BankManager>,
* nameAdmins: Promise<Store<NameHub, NameAdmin>>,
* },
* }} powers
* @typedef {*} BankManager // TODO
*/
export const makeBLDKit = async ({
consume: { agoricNames, bankManager, nameAdmins },
}) => {
const [issuerName, { bankDenom, bankPurse, issuerArgs }] = BLD_ISSUER_ENTRY;
assert(issuerArgs);
const kit = makeIssuerKit(issuerName, ...issuerArgs); // TODO: should this live in another vat???
await E(bankManager).addAsset(bankDenom, issuerName, bankPurse, kit);
const { brand, issuer } = kit;
const [issuerAdmin, brandAdmin] = await collectNameAdmins(
['issuer', 'brand'],
agoricNames,
nameAdmins,
);
return Promise.all([
E(issuerAdmin).update(issuerName, issuer),
E(brandAdmin).update(issuerName, brand),
]);
};
harden(makeBLDKit);

/**
* @param {{
* devices: { timer: unknown },
* vats: { timer: TimerVat },
* produce: { chainTimerService: Producer<ERef<TimerService>> }
* }} powers
*/
export const startTimerService = async ({
devices: { timer: timerDevice },
vats: { timer: timerVat },
produce: { chainTimerService },
}) => {
chainTimerService.resolve(E(timerVat).createTimerService(timerDevice));
};
harden(startTimerService);

/**
* @param {{
* consume: {
* loadVat: ERef<VatLoader<ProvisioningVat>>,
* chainBundler: ERef<ChainBundler>,
* },
* vats: { comms: CommsVatRoot, vattp: VattpVat },
* }} powers
* @typedef {ERef<ReturnType<import('../vat-provisioning.js').buildRootObject>>} ProvisioningVat
*/
export const registerProvisioner = async ({
consume: { chainBundler, loadVat },
vats: { comms, vattp },
}) => {
await E(E(loadVat)('provisioning')).register(chainBundler, comms, vattp);
};
Loading

0 comments on commit e1bb213

Please sign in to comment.