From bdbeec12e0e1283ac311edc676b20ac86cfda2a4 Mon Sep 17 00:00:00 2001 From: 0xPatrick Date: Tue, 17 Dec 2024 11:28:47 -0500 Subject: [PATCH 1/2] feat: `disableStorageNode` in `withOrchestration` opts --- .../src/exos/cosmos-orchestration-account.js | 43 +++++++++++-------- .../src/exos/local-chain-facade.js | 16 ++++--- .../src/exos/local-orchestration-account.js | 17 +++++--- .../src/exos/remote-chain-facade.js | 20 +++++---- .../orchestration/src/utils/start-helper.js | 20 +++++++-- 5 files changed, 75 insertions(+), 41 deletions(-) diff --git a/packages/orchestration/src/exos/cosmos-orchestration-account.js b/packages/orchestration/src/exos/cosmos-orchestration-account.js index a787ff8e39d..a711fb39f80 100644 --- a/packages/orchestration/src/exos/cosmos-orchestration-account.js +++ b/packages/orchestration/src/exos/cosmos-orchestration-account.js @@ -94,7 +94,7 @@ const { Vow$ } = NetworkShape; // TODO #9611 /** * @private * @typedef {{ - * topicKit: RecorderKit; + * topicKit: RecorderKit | undefined; * account: IcaAccount; * chainAddress: ChainAddress; * localAddress: LocalIbcAddress; @@ -291,26 +291,28 @@ export const prepareCosmosOrchestrationAccountKit = ( * @param {RemoteIbcAddress} info.remoteAddress * @param {object} io * @param {IcaAccount} io.account - * @param {Remote} io.storageNode + * @param {Remote | undefined} io.storageNode * @param {ICQConnection | undefined} io.icqConnection * @param {Remote} io.timer * @returns {State} */ ({ chainAddress, localAddress, remoteAddress }, io) => { const { storageNode } = io; - // must be the fully synchronous maker because the kit is held in durable state - const topicKit = makeRecorderKit(storageNode, PUBLIC_TOPICS.account[1]); - // TODO determine what goes in vstorage https://github.com/Agoric/agoric-sdk/issues/9066 - // XXX consider parsing local/remoteAddr to portId, channelId, counterpartyPortId, counterpartyChannelId, connectionId, counterpartyConnectionId - // FIXME these values will not update if IcaAccount gets new values after reopening. - // consider having IcaAccount responsible for the owning the writer. It might choose to share it with COA. - void E(topicKit.recorder).write( - /** @type {CosmosOrchestrationAccountStorageState} */ ({ - localAddress, - remoteAddress, - }), - ); - + let topicKit; + if (storageNode) { + // must be the fully synchronous maker because the kit is held in durable state + topicKit = makeRecorderKit(storageNode, PUBLIC_TOPICS.account[1]); + // TODO determine what goes in vstorage https://github.com/Agoric/agoric-sdk/issues/9066 + // XXX consider parsing local/remoteAddr to portId, channelId, counterpartyPortId, counterpartyChannelId, connectionId, counterpartyConnectionId + // FIXME these values will not update if IcaAccount gets new values after reopening. + // consider having IcaAccount responsible for the owning the writer. It might choose to share it with COA. + void E(topicKit.recorder).write( + /** @type {CosmosOrchestrationAccountStorageState} */ ({ + localAddress, + remoteAddress, + }), + ); + } const { account, icqConnection, timer } = io; return { account, @@ -333,6 +335,8 @@ export const prepareCosmosOrchestrationAccountKit = ( return account; }, getUpdater() { + if (!this.state.topicKit) + throw Fail`No topicKit; storageNode not provided`; return this.state.topicKit.recorder; }, /** @@ -731,6 +735,7 @@ export const prepareCosmosOrchestrationAccountKit = ( return asVow(async () => { await null; const { topicKit } = this.state; + if (!topicKit) throw Fail`No topicKit; storageNode not provided`; return harden({ account: { description: PUBLIC_TOPICS.account[0], @@ -1005,7 +1010,9 @@ export const prepareCosmosOrchestrationAccountKit = ( return watch(results, this.facets.delegationsQueryWatcher); }); }, - /** @type {HostOf} */ + /** + * @type {HostOf} + */ getUnbondingDelegation(validator) { return asVow(() => { trace('getUnbondingDelegation', validator); @@ -1024,7 +1031,9 @@ export const prepareCosmosOrchestrationAccountKit = ( return watch(results, this.facets.unbondingDelegationQueryWatcher); }); }, - /** @type {HostOf} */ + /** + * @type {HostOf} + */ getUnbondingDelegations() { return asVow(() => { trace('getUnbondingDelegations'); diff --git a/packages/orchestration/src/exos/local-chain-facade.js b/packages/orchestration/src/exos/local-chain-facade.js index 7f4ace2d8b4..dfa4061b183 100644 --- a/packages/orchestration/src/exos/local-chain-facade.js +++ b/packages/orchestration/src/exos/local-chain-facade.js @@ -36,7 +36,7 @@ import { chainFacadeMethods, TypedJsonShape } from '../typeGuards.js'; * @typedef {{ * makeLocalOrchestrationAccountKit: MakeLocalOrchestrationAccountKit; * orchestration: Remote; - * storageNode: Remote; + * storageNode: Remote | undefined; * agoricNames: Remote; * timer: Remote; * localchain: Remote; @@ -79,7 +79,7 @@ const prepareLocalChainFacadeKit = ( .returns(VowShape), }), makeChildNodeWatcher: M.interface('makeChildNodeWatcher', { - onFulfilled: M.call(M.remotable()) + onFulfilled: M.call(M.or(M.remotable(), M.undefined())) .optional({ account: M.remotable(), address: M.string() }) // empty context .returns(M.remotable()), }), @@ -145,11 +145,13 @@ const prepareLocalChainFacadeKit = ( * @param {[LocalChainAccount, ChainAddress['value']]} results */ onFulfilled([account, address]) { - return watch( - E(storageNode).makeChildNode(address), - this.facets.makeChildNodeWatcher, - { account, address }, - ); + const optionalStorageNode = storageNode + ? E(storageNode).makeChildNode(address) + : undefined; + return watch(optionalStorageNode, this.facets.makeChildNodeWatcher, { + account, + address, + }); }, }, makeChildNodeWatcher: { diff --git a/packages/orchestration/src/exos/local-orchestration-account.js b/packages/orchestration/src/exos/local-orchestration-account.js index 41d151475fd..bed3697611d 100644 --- a/packages/orchestration/src/exos/local-orchestration-account.js +++ b/packages/orchestration/src/exos/local-orchestration-account.js @@ -57,7 +57,7 @@ const EVow$ = shape => M.or(Vow$(shape), M.promise(/* shape */)); /** * @private * @typedef {{ - * topicKit: RecorderKit; + * topicKit: RecorderKit | undefined; * packetTools: PacketTools; * account: LocalChainAccount; * address: ChainAddress; @@ -181,14 +181,18 @@ export const prepareLocalOrchestrationAccountKit = ( * @param {object} initState * @param {LocalChainAccount} initState.account * @param {ChainAddress} initState.address - * @param {Remote} initState.storageNode + * @param {Remote | undefined} initState.storageNode * @returns {State} */ ({ account, address, storageNode }) => { - // must be the fully synchronous maker because the kit is held in durable state - const topicKit = makeRecorderKit(storageNode, PUBLIC_TOPICS.account[1]); - // TODO determine what goes in vstorage https://github.com/Agoric/agoric-sdk/issues/9066 - void E(topicKit.recorder).write(''); + let topicKit; + if (storageNode) { + // must be the fully synchronous maker because the kit is held in durable state + topicKit = makeRecorderKit(storageNode, PUBLIC_TOPICS.account[1]); + // TODO determine what goes in vstorage https://github.com/Agoric/agoric-sdk/issues/9066 + void E(topicKit.recorder).write(''); + } + const packetTools = makePacketTools(account); return { account, address, topicKit, packetTools }; @@ -548,6 +552,7 @@ export const prepareLocalOrchestrationAccountKit = ( return asVow(async () => { await null; const { topicKit } = this.state; + if (!topicKit) throw Fail`No topicKit; storageNode not provided`; return harden({ account: { description: PUBLIC_TOPICS.account[0], diff --git a/packages/orchestration/src/exos/remote-chain-facade.js b/packages/orchestration/src/exos/remote-chain-facade.js index 3349eb39c5d..ee22af9ba9c 100644 --- a/packages/orchestration/src/exos/remote-chain-facade.js +++ b/packages/orchestration/src/exos/remote-chain-facade.js @@ -33,7 +33,7 @@ const trace = makeTracer('RemoteChainFacade'); * typeof prepareCosmosOrchestrationAccount * >; * orchestration: Remote; - * storageNode: Remote; + * storageNode: Remote | undefined; * timer: Remote; * vowTools: VowTools; * }} RemoteChainFacadePowers @@ -94,7 +94,7 @@ const prepareRemoteChainFacadeKit = ( ).returns(VowShape), }), makeChildNodeWatcher: M.interface('makeChildNodeWatcher', { - onFulfilled: M.call(M.remotable(), { + onFulfilled: M.call(M.or(M.remotable(), M.undefined()), { account: M.remotable(), chainAddress: ChainAddressShape, localAddress: M.string(), @@ -210,16 +210,20 @@ const prepareRemoteChainFacadeKit = ( * @param {IcaAccount} account */ onFulfilled([chainAddress, localAddress, remoteAddress], account) { - return watch( - E(storageNode).makeChildNode(chainAddress.value), - this.facets.makeChildNodeWatcher, - { account, chainAddress, localAddress, remoteAddress }, - ); + const optionalStorageNode = storageNode + ? E(storageNode).makeChildNode(chainAddress.value) + : undefined; + return watch(optionalStorageNode, this.facets.makeChildNodeWatcher, { + account, + chainAddress, + localAddress, + remoteAddress, + }); }, }, makeChildNodeWatcher: { /** - * @param {Remote} childNode + * @param {Remote | undefined} childNode * @param {{ * account: IcaAccount; * chainAddress: ChainAddress; diff --git a/packages/orchestration/src/utils/start-helper.js b/packages/orchestration/src/utils/start-helper.js index e6c36bd523c..4efa79f24c6 100644 --- a/packages/orchestration/src/utils/start-helper.js +++ b/packages/orchestration/src/utils/start-helper.js @@ -32,6 +32,12 @@ import { makeZcfTools } from './zcf-tools.js'; * }} OrchestrationPowers */ +/** + * @typedef {{ + * disableStorageNode?: boolean; + * }} WithOrchestrationOpts + */ + /** * Helper that a contract start function can use to set up the objects needed * for orchestration. @@ -42,6 +48,7 @@ import { makeZcfTools } from './zcf-tools.js'; * @param {Baggage} baggage * @param {OrchestrationPowers} remotePowers * @param {Marshaller} marshaller + * @param {WithOrchestrationOpts} [opts] * @internal */ export const provideOrchestration = ( @@ -49,6 +56,7 @@ export const provideOrchestration = ( baggage, remotePowers, marshaller, + opts, ) => { // separate zones const zones = (() => { @@ -77,6 +85,10 @@ export const provideOrchestration = ( const zcfTools = makeZcfTools(zcf, vowTools); + const storageNode = opts?.disableStorageNode + ? undefined + : remotePowers.storageNode; + const { makeRecorderKit } = prepareRecorderKitMakers(baggage, marshaller); const makeLocalOrchestrationAccountKit = prepareLocalOrchestrationAccountKit( zones.orchestration, @@ -109,7 +121,7 @@ export const provideOrchestration = ( const makeRemoteChainFacade = prepareRemoteChainFacade(zones.orchestration, { makeCosmosOrchestrationAccount, orchestration: remotePowers.orchestrationService, - storageNode: remotePowers.storageNode, + storageNode, timer: remotePowers.timerService, vowTools, }); @@ -118,7 +130,7 @@ export const provideOrchestration = ( makeLocalOrchestrationAccountKit, localchain: remotePowers.localchain, // FIXME what path? - storageNode: remotePowers.storageNode, + storageNode, agoricNames, orchestration: remotePowers.orchestrationService, timer: remotePowers.timerService, @@ -199,16 +211,18 @@ harden(provideOrchestration); * zone: Zone, * tools: OrchestrationTools, * ) => Promise} contractFn + * @param {WithOrchestrationOpts} [opts] * @returns {(zcf: ZCF, privateArgs: PA, baggage: Baggage) => Promise} a * Zoe start function */ export const withOrchestration = - contractFn => async (zcf, privateArgs, baggage) => { + (contractFn, opts) => async (zcf, privateArgs, baggage) => { const { zone, ...tools } = provideOrchestration( zcf, baggage, privateArgs, privateArgs.marshaller, + opts, ); return contractFn(zcf, privateArgs, zone, tools); }; From fc56d7e6ae0b840813110063acb213692771aa69 Mon Sep 17 00:00:00 2001 From: 0xPatrick Date: Tue, 17 Dec 2024 11:32:40 -0500 Subject: [PATCH 2/2] chore(fusdc): use `WithOrchestrationOpts.disableStorageNode: true` --- .../boot/test/fast-usdc/fast-usdc.test.ts | 6 +---- .../fast-usdc/snapshots/fast-usdc.test.ts.md | 25 ------------------ .../snapshots/fast-usdc.test.ts.snap | Bin 2209 -> 1717 bytes packages/fast-usdc/src/fast-usdc.contract.js | 2 +- 4 files changed, 2 insertions(+), 31 deletions(-) diff --git a/packages/boot/test/fast-usdc/fast-usdc.test.ts b/packages/boot/test/fast-usdc/fast-usdc.test.ts index 3c17e8b6f55..1ce9659a8ec 100644 --- a/packages/boot/test/fast-usdc/fast-usdc.test.ts +++ b/packages/boot/test/fast-usdc/fast-usdc.test.ts @@ -180,11 +180,7 @@ test.serial('writes account addresses to vstorage', async t => { showValue: JSON.parse, pattern: /published\.fastUsdc\.(feeConfig|feedPolicy|poolMetrics)/, replacement: '', - note: `Under "published", the "fastUsdc" node is delegated to FastUSDC contract. - Note: published.fastUsdc.[settleAcctAddr], published.fastUsdc.[poolAcctAddr], - and published.fastUsdc.[intermediateAcctAddr] are published by @agoric/orchestration - via 'withOrchestration' and (local|cosmos)-orch-account-kit.js. - `, + owner: 'FastUSDC contract', }; await documentStorageSchema(t, storage, doc); diff --git a/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.md b/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.md index eae055ef42a..4d33aa399c9 100644 --- a/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.md +++ b/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.md @@ -120,10 +120,6 @@ Generated by [AVA](https://avajs.dev). ## writes account addresses to vstorage > Under "published", the "fastUsdc" node is delegated to FastUSDC contract. -> Note: published.fastUsdc.[settleAcctAddr], published.fastUsdc.[poolAcctAddr], -> and published.fastUsdc.[intermediateAcctAddr] are published by @agoric/orchestration -> via 'withOrchestration' and (local|cosmos)-orch-account-kit.js. -> > The example below illustrates the schema of the data published there. > > See also board marshalling conventions (_to appear_). @@ -136,27 +132,6 @@ Generated by [AVA](https://avajs.dev). settlementAccount: 'agoric1fakeLCAAddress1', }, ], - [ - 'published.fastUsdc.agoric1fakeLCAAddress', - { - body: '#""', - slots: [], - }, - ], - [ - 'published.fastUsdc.agoric1fakeLCAAddress1', - { - body: '#""', - slots: [], - }, - ], - [ - 'published.fastUsdc.noble1test', - { - body: '#{"localAddress":"/ibc-port/icacontroller-1/ordered/{\\"version\\":\\"ics27-1\\",\\"controllerConnectionId\\":\\"connection-72\\",\\"hostConnectionId\\":\\"connection-40\\",\\"address\\":\\"noble1test\\",\\"encoding\\":\\"proto3\\",\\"txType\\":\\"sdk_multi_msg\\"}/ibc-channel/channel-1","remoteAddress":"/ibc-hop/connection-72/ibc-port/icahost/ordered/{\\"version\\":\\"ics27-1\\",\\"controllerConnectionId\\":\\"connection-72\\",\\"hostConnectionId\\":\\"connection-40\\",\\"address\\":\\"noble1test\\",\\"encoding\\":\\"proto3\\",\\"txType\\":\\"sdk_multi_msg\\"}/ibc-channel/channel-1"}', - slots: [], - }, - ], ] ## makes usdc advance diff --git a/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.snap b/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.snap index c837074b0fac8a8353a3bc2e4a0b8b6253eecf4f..2cc93b6076a133849060edfdbbeda44db683cef1 100644 GIT binary patch literal 1717 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 { }; harden(contract); -export const start = withOrchestration(contract); +export const start = withOrchestration(contract, { disableStorageNode: true }); harden(start); /** @typedef {typeof start} FastUsdcSF */