-
Notifications
You must be signed in to change notification settings - Fork 5
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
fix: use limited publishBrandInfo power, not all of chainStorage #61
base: main
Are you sure you want to change the base?
Changes from all commits
0c894f6
6c724ff
b5c0fbc
227cc4b
3927d94
ad36e36
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// @ts-check | ||
import { E, Far } from '@endo/far'; | ||
|
||
const { Fail } = assert; | ||
|
||
// vstorage paths under published.* | ||
const BOARD_AUX = 'boardAux'; | ||
|
||
/** | ||
* @param {import('@agoric/zone').Zone} zone | ||
* @param {Marshaller} marshalData | ||
* @param {{ | ||
* board: ERef<import('./core-types').Board>; | ||
* chainStorage: ERef<StorageNode>; | ||
* }} powers | ||
*/ | ||
export const makeBoardAuxManager = (zone, marshalData, powers) => { | ||
const { board, chainStorage } = powers; | ||
const store = zone.mapStore('boardAux'); | ||
const boardAux = E(chainStorage).makeChildNode(BOARD_AUX); | ||
|
||
const formatValue = value => { | ||
const aux = marshalData.toCapData(value); | ||
// max length? | ||
return JSON.stringify(aux); | ||
}; | ||
|
||
const boardAuxNode = key => | ||
E.when(E(board).getId(key), boardId => E(boardAux).makeChildNode(boardId)); | ||
|
||
const init = async (key, value) => { | ||
store.init(key, value); | ||
await E(boardAuxNode(key)).setValue(formatValue(value)); | ||
}; | ||
|
||
const update = async (key, value) => { | ||
if (store.has(key)) { | ||
store.set(key, value); | ||
} else { | ||
store.init(key, value); | ||
} | ||
await E(boardAuxNode(key)).setValue(formatValue(value)); | ||
}; | ||
|
||
/** | ||
* Publish displayInfo of a brand to vstorage under its boardId. | ||
* | ||
* Works only once per brand. | ||
* @see {BoardAuxAdmin} to over-write aux info | ||
* | ||
* @param {Brand} brand | ||
*/ | ||
const publishBrandInfo = brand => | ||
E.when( | ||
Promise.all([E(brand).getAllegedName(), E(brand).getDisplayInfo()]), | ||
([allegedName, displayInfo]) => | ||
init(brand, harden({ allegedName, displayInfo })), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is goofy; I don't think this collection is keyed by brand |
||
); | ||
|
||
return harden({ | ||
brandAuxPublisher: Far('BrandAuxPublisher', { publishBrandInfo }), | ||
boardAuxTOFU: Far('BoardAuxTOFU', { publishBrandInfo, init }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Trust On First Use. Maybe should be renamed to "first come, first served". |
||
boardAuxAdmin: Far('BoardAuxAdmin', { publishBrandInfo, init, update }), | ||
}); | ||
}; | ||
/** @typedef {ReturnType<typeof makeBoardAuxManager>} BoardAuxManager */ | ||
|
||
/** @typedef {BoardAuxManager['brandAuxPublisher']} BrandAuxPublisher */ | ||
/** @typedef {BoardAuxManager['boardAuxTOFU']} BoardAuxTOFU */ | ||
/** @typedef {BoardAuxManager['boardAuxAdmin']} BoardAuxAdmin */ | ||
|
||
/** | ||
* @typedef {import('./core-types').PromiseSpaceOf<{ | ||
* brandAuxPublisher: BrandAuxPublisher; | ||
* boardAuxTOFU: BoardAuxTOFU; | ||
* boardAuxAdmin: BoardAuxAdmin; | ||
* }>} BoardAuxPowers | ||
*/ | ||
|
||
/** | ||
* @param {import('./core-types').BootstrapPowers | ||
* & import('./marshal-produce').Endo1Space | ||
* & BoardAuxPowers | ||
* } powers | ||
*/ | ||
export const produceBoardAuxManager = async powers => { | ||
const { zone } = powers; | ||
const { board, chainStorage, endo1 } = powers.consume; | ||
const { marshal } = await endo1; | ||
const { makeMarshal } = marshal; | ||
const marshalData = makeMarshal(_val => Fail`data only`); | ||
|
||
const mgr = makeBoardAuxManager(zone, marshalData, { board, chainStorage }); | ||
powers.produce.brandAuxPublisher.reset(); | ||
powers.produce.boardAuxTOFU.reset(); | ||
powers.produce.boardAuxAdmin.reset(); | ||
powers.produce.brandAuxPublisher.resolve(mgr.brandAuxPublisher); | ||
powers.produce.boardAuxTOFU.resolve(mgr.boardAuxTOFU); | ||
powers.produce.boardAuxAdmin.resolve(mgr.boardAuxAdmin); | ||
}; | ||
|
||
export const permit = { | ||
zone: true, | ||
consume: { board: true, chainStorage: true, endo1: true }, | ||
produce: { | ||
brandAuxPublisher: true, | ||
boardAuxTOFU: true, | ||
boardAuxAdmin: true, | ||
}, | ||
}; | ||
|
||
export const manifest = { | ||
[produceBoardAuxManager.name]: permit, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import type { Zone } from '@agoric/zone'; | ||
|
||
// XXX how to import types from @agoric/vats? | ||
// cf. https://github.com/Agoric/agoric-sdk/blob/master/packages/vats/src/core/types-ambient.d.ts | ||
type Board = { getId: (key: unknown) => string }; | ||
|
||
type WellKnown = { | ||
asset: 'BLD' | 'IST'; | ||
contract: 'VaultFactory' | 'FeeDistributor'; | ||
}; | ||
|
||
// TODO: include AssetKind { IST: 'nat', ... } | ||
type AssetsSpace<T extends string> = { | ||
brand: PromiseSpaceOf<Record<T, Brand>>; | ||
issuer: PromiseSpaceOf<Record<T, Issuer>>; | ||
}; | ||
|
||
// TODO: include contract start function types | ||
type ContractSpace<T extends string> = { | ||
installation: PromiseSpaceOf<Record<T, Installation>>; | ||
instance: PromiseSpaceOf<Record<T, Instance>>; | ||
}; | ||
|
||
type WellKnownSpaces = AssetsSpace<WellKnown['asset']> & | ||
ContractSpace<WellKnown['contract']>; | ||
|
||
type BootstrapSpace = PromiseSpaceOf<{ | ||
chainStorage: StorageNode; | ||
board: Board; | ||
startUpgradable: (...args: unknown[]) => any; | ||
zoe: ZoeService; | ||
}>; | ||
|
||
type BootstrapPowers = BootstrapSpace & | ||
WellKnownSpaces & { | ||
zone: Zone; | ||
}; | ||
|
||
type Producer<T> = { | ||
resolve: (v: ERef<T>) => void; | ||
reject: (r: unknown) => void; | ||
reset: (reason?: unknown) => void; | ||
}; | ||
|
||
/** | ||
* @template B - Bidirectional | ||
* @template C - Consume only | ||
* @template P - Produce only | ||
*/ | ||
type PromiseSpaceOf<B, C = {}, P = {}> = { | ||
consume: { [K in keyof (B & C)]: Promise<(B & C)[K]> }; | ||
produce: { [K in keyof (B & P)]: Producer<(B & P)[K]> }; | ||
}; | ||
|
||
type BootstrapManifestPermit = | ||
| true | ||
| string | ||
| { [key: string]: BootstrapManifestPermit }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// @ts-check | ||
import * as marshal from '@endo/marshal'; | ||
import * as patterns from '@endo/patterns'; | ||
|
||
/** | ||
* @typedef {{ | ||
* endo1: { | ||
* marshal: typeof import('@endo/marshal'); | ||
* patterns: typeof import('@endo/patterns'); | ||
* } | ||
* }} Endo1Modules | ||
Comment on lines
+7
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is cool! Why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cuz it doesn't have all of the endo modules; just the ones needed by this 1st use case but that reminds me... I should get input from endo folks such as @kriskowal |
||
* @typedef {import('./core-types').PromiseSpaceOf<Endo1Modules>} Endo1Space | ||
*/ | ||
|
||
/** | ||
* Make @endo/marshal, @endo/patterns available to CoreEval scripts. | ||
* | ||
* @param {import('./core-types').BootstrapPowers & Endo1Space} permittedPowers | ||
*/ | ||
export const produceEndoModules = permittedPowers => { | ||
const { produce } = permittedPowers; | ||
const endo = { marshal, patterns }; | ||
produce.endo1.resolve(endo); | ||
}; | ||
|
||
/** @type {import('./core-types').BootstrapManifestPermit} */ | ||
export const permit = { | ||
/** @type {Record<keyof Endo1Modules, true>} */ | ||
produce: { endo1: true }, | ||
}; | ||
|
||
export const manifest = { | ||
[produceEndoModules.name]: permit, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅