diff --git a/packages/inter-protocol/src/price/priceAggregatorChainlink.js b/packages/inter-protocol/src/price/priceAggregatorChainlink.js index 68dfe6071b5..0d5f8d60fd2 100644 --- a/packages/inter-protocol/src/price/priceAggregatorChainlink.js +++ b/packages/inter-protocol/src/price/priceAggregatorChainlink.js @@ -13,7 +13,7 @@ import { import { makeScalarBigMapStore } from '@agoric/vat-data'; import { makeOnewayPriceAuthorityKit, - makePublicTopicProvider, + makeStorageNodePathProvider, } from '@agoric/zoe/src/contractSupport/index.js'; import { E } from '@endo/eventual-send'; import { Far } from '@endo/marshal'; @@ -141,7 +141,7 @@ export const start = async (zcf, privateArgs, baggage) => { const latestRoundStorageNode = E(storageNode).makeChildNode('latestRound'); pipeTopicToStorage(latestRoundSubscriber, latestRoundStorageNode, marshaller); - const providePublicTopic = makePublicTopicProvider(); + const memoizedPath = makeStorageNodePathProvider(baggage); /** @type {MapStore} */ const oracles = makeScalarBigMapStore('oracles', { @@ -326,16 +326,16 @@ export const start = async (zcf, privateArgs, baggage) => { }, getPublicTopics() { return { - quotes: providePublicTopic( - 'Quotes from this price aggregator', - quoteSubscriber, - storageNode, - ), - latestRound: providePublicTopic( - 'Notification of each round', - latestRoundSubscriber, - latestRoundStorageNode, - ), + quotes: { + description: 'Quotes from this price aggregator', + subscriber: quoteSubscriber, + storagePath: memoizedPath(storageNode), + }, + latestRound: { + description: 'Notification of each round', + subscriber: latestRoundSubscriber, + storagePath: memoizedPath(latestRoundStorageNode), + }, }; }, }); diff --git a/packages/inter-protocol/src/vaultFactory/vaultHolder.js b/packages/inter-protocol/src/vaultFactory/vaultHolder.js index 41a670efcfc..ddb87c1f933 100644 --- a/packages/inter-protocol/src/vaultFactory/vaultHolder.js +++ b/packages/inter-protocol/src/vaultFactory/vaultHolder.js @@ -3,13 +3,13 @@ */ import { AmountShape } from '@agoric/ertp'; import { - SubscriberShape, - prepareDurablePublishKit, pipeTopicToStorage, + prepareDurablePublishKit, + SubscriberShape, TopicsRecordShape, } from '@agoric/notifier'; import { M, prepareExoClassKit } from '@agoric/vat-data'; -import { makePublicTopicProvider } from '@agoric/zoe/src/contractSupport/durability.js'; +import { makeStorageNodePathProvider } from '@agoric/zoe/src/contractSupport/durability.js'; import { UnguardedHelperI } from '../typeGuards.js'; const { Fail } = assert; @@ -39,7 +39,7 @@ const HolderI = M.interface('holder', { * @param {ERef} marshaller */ export const prepareVaultHolder = (baggage, marshaller) => { - const providePublicTopic = makePublicTopicProvider(); + const memoizedPath = makeStorageNodePathProvider(baggage); const makeVaultHolderPublishKit = prepareDurablePublishKit( baggage, @@ -91,11 +91,11 @@ export const prepareVaultHolder = (baggage, marshaller) => { getPublicTopics() { const { subscriber, storageNode } = this.state; return harden({ - vault: providePublicTopic( - 'Vault holder status', + vault: { + description: 'Vault holder status', subscriber, - storageNode, - ), + storagePath: memoizedPath(storageNode), + }, }); }, makeAdjustBalancesInvitation() { diff --git a/packages/smart-wallet/src/smartWallet.js b/packages/smart-wallet/src/smartWallet.js index 0c00e269d00..a177e76ecb3 100644 --- a/packages/smart-wallet/src/smartWallet.js +++ b/packages/smart-wallet/src/smartWallet.js @@ -17,7 +17,7 @@ import { import { StorageNodeShape } from '@agoric/notifier/src/typeGuards.js'; import { M, mustMatch } from '@agoric/store'; import { makeScalarBigMapStore, prepareExoClassKit } from '@agoric/vat-data'; -import { makePublicTopicProvider } from '@agoric/zoe/src/contractSupport/index.js'; +import { makeStorageNodePathProvider } from '@agoric/zoe/src/contractSupport/durability.js'; import { E } from '@endo/far'; import { makeInvitationsHelper } from './invitations.js'; import { makeOfferExecutor } from './offers.js'; @@ -159,7 +159,7 @@ export const prepareSmartWallet = (baggage, shared) => { 'Smart Wallet publish kit', ); - const providePublicTopic = makePublicTopicProvider(); + const memoizedPath = makeStorageNodePathProvider(baggage); /** * @@ -557,16 +557,16 @@ export const prepareSmartWallet = (baggage, shared) => { walletStorageNode, } = this.state; return harden({ - current: providePublicTopic( - 'Current state of wallet', - currentPublishKit.subscriber, - currentStorageNode, - ), - updates: providePublicTopic( - 'Changes to wallet', - updatePublishKit.subscriber, - walletStorageNode, - ), + current: { + description: 'Current state of wallet', + subscriber: currentPublishKit.subscriber, + storagePath: memoizedPath(currentStorageNode), + }, + updates: { + description: 'Changes to wallet', + subscriber: updatePublishKit.subscriber, + storagePath: memoizedPath(walletStorageNode), + }, }); }, }, diff --git a/packages/zoe/src/contractSupport/durability.js b/packages/zoe/src/contractSupport/durability.js index e365b88308c..3e1f52e23ed 100644 --- a/packages/zoe/src/contractSupport/durability.js +++ b/packages/zoe/src/contractSupport/durability.js @@ -1,16 +1,20 @@ -import { makePublicTopic, SubscriberShape } from '@agoric/notifier'; -import { StorageNodeShape } from '@agoric/notifier/src/typeGuards.js'; -import { M, mustMatch } from '@agoric/store'; +import { makeAtomicProvider } from '@agoric/store/src/stores/store-utils.js'; import { makeScalarBigMapStore, provide, + provideDurableMapStore, provideDurableSetStore, } from '@agoric/vat-data'; +import { E } from '@endo/eventual-send'; import { Far } from '@endo/marshal'; /// /** + * SCALE: Only for low cardinality provisioning. Every value from init() will + * remain in the map for the lifetime of the heap. If a key object is GCed, its + * representative also remains. + * * @template {{}} E Ephemeral state * @param {() => E} init */ @@ -37,47 +41,19 @@ harden(makeEphemeraProvider); /** * + * @param {import('@agoric/vat-data').Baggage} baggage */ -export const makePublicTopicProvider = () => { - /** @type {WeakMap, import('@agoric/notifier').PublicTopic>} */ - const extant = new WeakMap(); - - /** - * Provide a PublicTopic for the specified durable subscriber. - * Memoizes the resolution of the promise for the storageNode's path, for the lifetime of the vat. - * - * @template {object} T - * @param {string} description - * @param {Subscriber} durableSubscriber primary key - * @param {ERef} storageNode - * @returns {import('@agoric/notifier').PublicTopic} - */ - const providePublicTopic = (description, durableSubscriber, storageNode) => { - if (extant.has(durableSubscriber)) { - // @ts-expect-error cast - return extant.get(durableSubscriber); - } - mustMatch( - harden({ description, durableSubscriber, storageNode }), - harden({ - description: M.string(), - durableSubscriber: SubscriberShape, - storageNode: M.eref(StorageNodeShape), - }), - ); - - /** @type {import('@agoric/notifier').PublicTopic} */ - const newMeta = makePublicTopic( - description, - durableSubscriber, - storageNode, - ); - extant.set(durableSubscriber, newMeta); - return newMeta; +export const makeStorageNodePathProvider = baggage => { + /** @type {import('@agoric/store/src/stores/store-utils.js').AtomicProvider} */ + const nodePaths = makeAtomicProvider( + provideDurableMapStore(baggage, 'storage node paths'), + ); + /** @param {ERef} nodeP */ + return async nodeP => { + const node = await nodeP; + return nodePaths.provideAsync(node, n => E(n).getPath()); }; - return providePublicTopic; }; -harden(makePublicTopicProvider); /** * Provide an empty ZCF seat.