From 0b82c2900e049021bf9ece3bebff6cd764dd18f3 Mon Sep 17 00:00:00 2001 From: Mathieu Hofman Date: Tue, 23 Jul 2024 01:45:32 +0000 Subject: [PATCH 1/4] feat(vow): abandoned errors are retriable --- packages/internal/src/upgrade-api.js | 20 +++++++++++++++++++- packages/internal/test/upgrade-api.test.js | 15 +++++++++++++++ packages/vow/vat.js | 12 ++++++++++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/packages/internal/src/upgrade-api.js b/packages/internal/src/upgrade-api.js index c2cadd7be165..a1b0fa9c640c 100644 --- a/packages/internal/src/upgrade-api.js +++ b/packages/internal/src/upgrade-api.js @@ -45,5 +45,23 @@ harden(makeUpgradeDisconnection); * @returns {reason is UpgradeDisconnection} */ export const isUpgradeDisconnection = reason => - isFrozen(reason) && matches(reason, UpgradeDisconnectionShape); + reason != null && // eslint-disable-line eqeqeq + isFrozen(reason) && + matches(reason, UpgradeDisconnectionShape); harden(isUpgradeDisconnection); + +/** + * Returns whether a reason is a 'vat terminated' error generated when an object + * is abandoned by a vat during an upgrade. + * + * @param {any} reason + * @returns {reason is Error} + */ +export const isAbandonedError = reason => + reason != null && // eslint-disable-line eqeqeq + isFrozen(reason) && + matches(reason, M.error()) && + // We're not using a constant here since this special value is already + // sprinkled throughout the SDK + reason.message === 'vat terminated'; +harden(isAbandonedError); diff --git a/packages/internal/test/upgrade-api.test.js b/packages/internal/test/upgrade-api.test.js index 5ffc38f9b29f..f8eee5d2d926 100644 --- a/packages/internal/test/upgrade-api.test.js +++ b/packages/internal/test/upgrade-api.test.js @@ -1,8 +1,11 @@ // @ts-check import test from 'ava'; +import { makeMarshal } from '@endo/marshal'; + import { makeUpgradeDisconnection, isUpgradeDisconnection, + isAbandonedError, } from '../src/upgrade-api.js'; test('isUpgradeDisconnection must recognize disconnection objects', t => { @@ -18,3 +21,15 @@ test('isUpgradeDisconnection must recognize original-format disconnection object }); t.true(isUpgradeDisconnection(disconnection)); }); + +test('isAbandonedError recognizes marshalled vat terminated errors', t => { + const { fromCapData, toCapData } = makeMarshal(undefined, undefined, { + serializeBodyFormat: 'smallcaps', + errorIdNum: 70_000, + marshalSaveError: () => {}, + }); + const error = harden(Error('vat terminated')); + const remoteError = fromCapData(toCapData(error)); + + t.true(isAbandonedError(remoteError)); +}); diff --git a/packages/vow/vat.js b/packages/vow/vat.js index cc1170eaa7e4..a0c24a90510d 100644 --- a/packages/vow/vat.js +++ b/packages/vow/vat.js @@ -5,7 +5,10 @@ /* global globalThis */ // @ts-check -import { isUpgradeDisconnection } from '@agoric/internal/src/upgrade-api.js'; +import { + isUpgradeDisconnection, + isAbandonedError, +} from '@agoric/internal/src/upgrade-api.js'; import { makeHeapZone } from '@agoric/base-zone/heap.js'; import { makeE, prepareVowTools as rawPrepareVowTools } from './src/index.js'; @@ -13,11 +16,16 @@ import { makeE, prepareVowTools as rawPrepareVowTools } from './src/index.js'; const isRetryableReason = (reason, priorRetryValue) => { if ( isUpgradeDisconnection(reason) && - (!priorRetryValue || + (!isUpgradeDisconnection(priorRetryValue) || reason.incarnationNumber > priorRetryValue.incarnationNumber) ) { return reason; } + // For abandoned errors there is no way to differentiate errors from + // consecutive upgrades + if (isAbandonedError(reason) && !isAbandonedError(priorRetryValue)) { + return reason; + } return undefined; }; From 5fb0456baf3acabd89abcd72a8e56ef9da7062a1 Mon Sep 17 00:00:00 2001 From: Mathieu Hofman Date: Tue, 23 Jul 2024 07:36:11 +0000 Subject: [PATCH 2/4] WIP feat(vow): retriable tools --- packages/vow/src/retriable.js | 218 ++++++++++++++++++++++++++++++++++ packages/vow/src/tools.js | 22 +--- 2 files changed, 223 insertions(+), 17 deletions(-) create mode 100644 packages/vow/src/retriable.js diff --git a/packages/vow/src/retriable.js b/packages/vow/src/retriable.js new file mode 100644 index 000000000000..c58e7621cfdf --- /dev/null +++ b/packages/vow/src/retriable.js @@ -0,0 +1,218 @@ +import { Fail } from '@endo/errors'; +import { M } from '@endo/patterns'; +import { PromiseWatcherI } from '@agoric/base-zone'; +import { toPassableCap, VowShape } from './vow-utils.js'; + +/** + * @import {WeakMapStore} from '@agoric/store' + * @import {Zone} from '@agoric/base-zone' + * @import {Vow, VowKit, IsRetryableReason} from './types.js' + * @import {Passable} from '@endo/pass-style' + */ + +/** + * @typedef {object} PreparationOptions + * @property {() => VowKit} makeVowKit + * @property {IsRetryableReason} isRetryableReason + */ + +/** + * @template {Passable[]} [TArgs=Passable[]] + * @template {any} [TRet=any] + * @typedef {(...args: TArgs) => Promise} RetriableFunc + */ + +const { defineProperties } = Object; + +const RetriableFlowIKit = harden({ + flow: M.interface('Flow', { + restart: M.call().returns(), + getOutcome: M.call().returns(VowShape), + }), + resultWatcher: PromiseWatcherI, +}); + +const AdminRetriableFlowI = M.interface('RetriableFlowAdmin', { + getFlowForOutcomeVow: M.call(VowShape).returns(M.opt(M.remotable('flow'))), +}); + +/** + * @param {Zone} outerZone + * @param {PreparationOptions} [outerOptions] + */ +export const prepareRetriableTools = (outerZone, outerOptions = {}) => { + const { makeVowKit, isRetryableReason } = outerOptions; + + /** + * So we can give out wrapper functions easily and recover flow objects + * for their activations later. + */ + const flowForOutcomeVowKey = outerZone.mapStore( + 'retriableFlowForOutcomeVow', + { + keyShape: M.remotable('toPassableCap'), + valueShape: M.remotable('flow'), // isDone === false + }, + ); + + /** + * @param {Zone} zone + * @param {string} tag + * @param {RetriableFunc} retriableFunc + */ + const prepareRetriableFlowKit = (zone, tag, retriableFunc) => { + typeof retriableFunc === 'function' || + Fail`retriableFunc must be a callable function ${retriableFunc}`; + + const internalMakeRetriableFlowKit = zone.exoClassKit( + tag, + RetriableFlowIKit, + activationArgs => { + harden(activationArgs); + + return { + activationArgs, // restarting the retriable function uses the original args + outcomeKit: makeVowKit(), // outcome of activation as vow + lastRetryReason: undefined, + runs: 0n, + isDone: false, // persistently done + }; + }, + { + flow: { + /** + * Calls the retriable function, either for the initial run or when + * the result of the previous run fails with a retriable reason. + */ + restart() { + const { state, facets } = this; + const { activationArgs, isDone } = state; + const { flow, resultWatcher } = facets; + + !isDone || + // separate line so I can set a breakpoint + Fail`Cannot restart a done retriable flow ${flow}`; + + const runId = state.runs + 1n; + state.runs = runId; + + let resultP; + try { + resultP = Promise.resolve(retriableFunc(...activationArgs)); + } catch (err) { + resultP = Promise.resolve(() => Promise.reject(err)); + } + + outerZone.watchPromise(harden(resultP), resultWatcher, runId); + }, + getOutcome() { + const { state } = this; + const { outcomeKit } = state; + return outcomeKit.vow; + }, + }, + resultWatcher: { + onFulfilled(value, runId) { + const { state } = this; + const { runs, outcomeKit } = state; + if (runId !== runs) return; + !state.isDone || + Fail`Cannot resolve a done retriable flow ${this.facets.flow}`; + outcomeKit.resolver.resolve(value); + flowForOutcomeVowKey.delete(toPassableCap(outcomeKit.vow)); + state.isDone = true; + }, + onRejected(reason, runId) { + const { state } = this; + const { runs, outcomeKit } = state; + if (runId !== runs) return; + !state.isDone || + Fail`Cannot reject a done retriable flow ${this.facets.flow}`; + const retryReason = isRetryableReason( + reason, + state.lastRetryReason, + ); + if (retryReason) { + state.lastRetryReason = retryReason; + this.facets.flow.restart(); + } else { + outcomeKit.resolver.reject(reason); + flowForOutcomeVowKey.delete(toPassableCap(outcomeKit.vow)); + state.isDone = true; + } + }, + }, + }, + ); + const makeRetriableFlowKit = activationArgs => { + const retriableKit = internalMakeRetriableFlowKit(activationArgs); + const { flow } = retriableKit; + + const vow = flow.getOutcome(); + flowForOutcomeVowKey.init(toPassableCap(vow), flow); + flow.restart(); + return retriableKit; + }; + return harden(makeRetriableFlowKit); + }; + + /** + * @template {RetriableFunc} F + * @param {Zone} zone + * @param {string} tag + * @param {F} retriableFunc + */ + const retriable = (zone, tag, retriableFunc) => { + const makeRetriableKit = prepareRetriableFlowKit(zone, tag, retriableFunc); + const wrapperFuncName = `${tag}_retriable`; + + const wrapperFunc = { + /** @type {(...args: Parameters) => Vow>>} */ + [wrapperFuncName](...args) { + const { flow } = makeRetriableKit(args); + return flow.getOutcome(); + }, + }[wrapperFuncName]; + defineProperties(wrapperFunc, { + length: { value: retriableFunc.length }, + }); + return harden(wrapperFunc); + }; + + const adminRetriableFlow = outerZone.exo( + 'AdminRetriableFlow', + AdminRetriableFlowI, + { + getFlowForOutcomeVow(outcomeVow) { + return flowForOutcomeVowKey.get(toPassableCap(outcomeVow)); + }, + }, + ); + + return harden({ + prepareRetriableFlowKit, + adminRetriableFlow, + retriable, + }); +}; +harden(prepareRetriableTools); + +/** + * @typedef {ReturnType} RetriableTools + */ + +/** + * @typedef {RetriableTools['adminRetriableFlow']} AdminRetriableFlow + */ + +/** + * @typedef {ReturnType} MakeRetriableFlowKit + */ + +/** + * @typedef {ReturnType} RetriableFlowKit + */ + +/** + * @typedef {RetriableFlowKit['flow']} RetriableFlow + */ diff --git a/packages/vow/src/tools.js b/packages/vow/src/tools.js index ec224cbe0789..905fa2606b04 100644 --- a/packages/vow/src/tools.js +++ b/packages/vow/src/tools.js @@ -3,6 +3,7 @@ import { makeAsVow } from './vow-utils.js'; import { prepareVowKit } from './vow.js'; import { prepareWatchUtils } from './watch-utils.js'; import { prepareWatch } from './watch.js'; +import { prepareRetriableTools } from './retriable.js'; import { makeWhen } from './when.js'; /** @@ -33,23 +34,10 @@ export const prepareVowTools = (zone, powers = {}) => { const watchUtils = makeWatchUtils(); const asVow = makeAsVow(makeVowKit); - /** - * TODO FIXME make this real - * Create a function that retries the given function if the underlying - * functions rejects due to upgrade disconnection. - * - * @template {(...args: any[]) => Promise} F - * @param {Zone} fnZone - the zone for the named function - * @param {string} name - * @param {F} fn - * @returns {F extends (...args: infer Args) => Promise ? (...args: Args) => Vow : never} - */ - const retriable = - (fnZone, name, fn) => - // @ts-expect-error cast - (...args) => { - return watch(fn(...args)); - }; + const { retriable } = prepareRetriableTools(zone, { + makeVowKit, + isRetryableReason, + }); /** * Vow-tolerant implementation of Promise.all. From 1633c88887d34cc1826f91808447b6551d97a961 Mon Sep 17 00:00:00 2001 From: Mathieu Hofman Date: Tue, 23 Jul 2024 08:25:52 +0000 Subject: [PATCH 3/4] WIP fix(orchestration): chainHub accepts zone --- packages/orchestration/src/examples/stakeBld.contract.js | 2 +- packages/orchestration/src/exos/chain-hub.js | 7 +++---- packages/orchestration/src/proposals/start-stakeAtom.js | 9 +++++++-- packages/orchestration/src/proposals/start-stakeOsmo.js | 9 +++++++-- packages/orchestration/src/utils/start-helper.js | 3 ++- packages/orchestration/test/exos/chain-hub.test.ts | 4 ++-- packages/orchestration/test/exos/make-test-loa-kit.ts | 2 +- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/orchestration/src/examples/stakeBld.contract.js b/packages/orchestration/src/examples/stakeBld.contract.js index 935c72b92263..d8cc34d18296 100644 --- a/packages/orchestration/src/examples/stakeBld.contract.js +++ b/packages/orchestration/src/examples/stakeBld.contract.js @@ -47,7 +47,7 @@ export const start = async (zcf, privateArgs, baggage) => { zcf, privateArgs.timerService, vowTools, - makeChainHub(privateArgs.agoricNames, vowTools), + makeChainHub(zone.subZone('chainHub'), privateArgs.agoricNames, vowTools), ); // ---------------- diff --git a/packages/orchestration/src/exos/chain-hub.js b/packages/orchestration/src/exos/chain-hub.js index 7f235bac09cd..8d4ac801a04c 100644 --- a/packages/orchestration/src/exos/chain-hub.js +++ b/packages/orchestration/src/exos/chain-hub.js @@ -3,7 +3,6 @@ import { E } from '@endo/far'; import { M } from '@endo/patterns'; import { VowShape } from '@agoric/vow'; -import { makeHeapZone } from '@agoric/zone'; import { CosmosChainInfoShape, IBCConnectionInfoShape } from '../typeGuards.js'; /** @@ -149,18 +148,18 @@ const ChainHubI = M.interface('ChainHub', { }); /** - * Make a new ChainHub in the zone (or in the heap if no zone is provided). + * Make a new ChainHub in the zone. * * The resulting object is an Exo singleton. It has no precious state. It's only * state is a cache of queries to agoricNames and whatever info was provided in * registration calls. When you need a newer version you can simply make a hub * hub and repeat the registrations. * + * @param {Zone} zone * @param {Remote} agoricNames * @param {VowTools} vowTools */ -export const makeChainHub = (agoricNames, vowTools) => { - const zone = makeHeapZone(); +export const makeChainHub = (zone, agoricNames, vowTools) => { /** @type {MapStore} */ const chainInfos = zone.mapStore('chainInfos', { keyShape: M.string(), diff --git a/packages/orchestration/src/proposals/start-stakeAtom.js b/packages/orchestration/src/proposals/start-stakeAtom.js index 8035f4fda1c1..a9e0e9e3282a 100644 --- a/packages/orchestration/src/proposals/start-stakeAtom.js +++ b/packages/orchestration/src/proposals/start-stakeAtom.js @@ -46,8 +46,13 @@ export const startStakeAtom = async ({ const storageNode = await makeStorageNodeChild(chainStorage, VSTORAGE_PATH); const marshaller = await E(board).getPublishingMarshaller(); - const vt = prepareVowTools(makeHeapZone()); - const chainHub = makeChainHub(await agoricNames, vt); + const zone = makeHeapZone(); + const vt = prepareVowTools(zone.subZone('vows')); + const chainHub = makeChainHub( + zone.subZone('chainHub'), + await agoricNames, + vt, + ); const [_, cosmoshub, connectionInfo] = await vt.when( chainHub.getChainsAndConnection('agoric', 'cosmoshub'), diff --git a/packages/orchestration/src/proposals/start-stakeOsmo.js b/packages/orchestration/src/proposals/start-stakeOsmo.js index 6fda8e812de2..083c4c6449b2 100644 --- a/packages/orchestration/src/proposals/start-stakeOsmo.js +++ b/packages/orchestration/src/proposals/start-stakeOsmo.js @@ -51,8 +51,13 @@ export const startStakeOsmo = async ({ const storageNode = await makeStorageNodeChild(chainStorage, VSTORAGE_PATH); const marshaller = await E(board).getPublishingMarshaller(); - const vt = prepareVowTools(makeHeapZone()); - const chainHub = makeChainHub(await agoricNames, vt); + const zone = makeHeapZone(); + const vt = prepareVowTools(zone.subZone('vows')); + const chainHub = makeChainHub( + zone.subZone('chainHub'), + await agoricNames, + vt, + ); const [_, osmosis, connectionInfo] = await vt.when( chainHub.getChainsAndConnection('agoric', 'osmosis'), diff --git a/packages/orchestration/src/utils/start-helper.js b/packages/orchestration/src/utils/start-helper.js index 9f9b9ac417fb..2036731e51df 100644 --- a/packages/orchestration/src/utils/start-helper.js +++ b/packages/orchestration/src/utils/start-helper.js @@ -62,6 +62,7 @@ export const provideOrchestration = ( /** for contract-provided names */ contract: zone.subZone('contract'), orchestration: zone.subZone('orchestration'), + chainHub: zone.subZone('chainHub'), vows: zone.subZone('vows'), zoe: zone.subZone('zoe'), }; @@ -71,7 +72,7 @@ export const provideOrchestration = ( const vowTools = prepareVowTools(zones.vows); - const chainHub = makeChainHub(agoricNames, vowTools); + const chainHub = makeChainHub(zones.chainHub, agoricNames, vowTools); const zoeTools = makeZoeTools(zones.zoe, { zcf, vowTools }); diff --git a/packages/orchestration/test/exos/chain-hub.test.ts b/packages/orchestration/test/exos/chain-hub.test.ts index 446c6c02bd43..17a15d6acc17 100644 --- a/packages/orchestration/test/exos/chain-hub.test.ts +++ b/packages/orchestration/test/exos/chain-hub.test.ts @@ -36,9 +36,9 @@ const connection = { // fresh state for each test const setup = () => { const zone = provideDurableZone('root'); - const vt = prepareSwingsetVowTools(zone); + const vt = prepareSwingsetVowTools(zone.subZone('vows')); const { nameHub, nameAdmin } = makeNameHubKit(); - const chainHub = makeChainHub(nameHub, vt); + const chainHub = makeChainHub(zone.subZone('chainHub'), nameHub, vt); return { chainHub, nameAdmin, vt }; }; diff --git a/packages/orchestration/test/exos/make-test-loa-kit.ts b/packages/orchestration/test/exos/make-test-loa-kit.ts index 765e7d48f584..f7c53b0a803d 100644 --- a/packages/orchestration/test/exos/make-test-loa-kit.ts +++ b/packages/orchestration/test/exos/make-test-loa-kit.ts @@ -39,7 +39,7 @@ export const prepareMakeTestLOAKit = ( zcf, timer, vowTools, - makeChainHub(agoricNames, vowTools), + makeChainHub(rootZone.subZone('chainHub'), agoricNames, vowTools), ); return async ({ From a36498aeb8df65257bc4d0841e3cf338f928bae2 Mon Sep 17 00:00:00 2001 From: Mathieu Hofman Date: Tue, 23 Jul 2024 08:27:44 +0000 Subject: [PATCH 4/4] WIP Update test snapshots --- .../snapshots/sendAnywhere.test.ts.md | 17 +++- .../snapshots/sendAnywhere.test.ts.snap | Bin 954 -> 1150 bytes .../snapshots/unbondExample.test.ts.md | 87 +++++++++++++++++- .../snapshots/unbondExample.test.ts.snap | Bin 786 -> 1721 bytes 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/packages/orchestration/test/examples/snapshots/sendAnywhere.test.ts.md b/packages/orchestration/test/examples/snapshots/sendAnywhere.test.ts.md index 95beb6676c24..9cc05e0959fb 100644 --- a/packages/orchestration/test/examples/snapshots/sendAnywhere.test.ts.md +++ b/packages/orchestration/test/examples/snapshots/sendAnywhere.test.ts.md @@ -24,11 +24,21 @@ Generated by [AVA](https://avajs.dev). flowForOutcomeVow: {}, unwrapMap: 'Alleged: weakMapStore', }, + chainHub: { + ChainHub_kindHandle: 'Alleged: kind', + ChainHub_singleton: 'Alleged: ChainHub', + chainInfos: {}, + connectionInfos: {}, + lookupChainInfo_kindHandle: 'Alleged: kind', + lookupChainsAndConnection_kindHandle: 'Alleged: kind', + lookupConnectionInfo_kindHandle: 'Alleged: kind', + }, contract: { 'ChainHub Admin_kindHandle': 'Alleged: kind', 'ChainHub Admin_singleton': 'Alleged: ChainHub Admin', 'Send PF_kindHandle': 'Alleged: kind', 'Send PF_singleton': 'Alleged: Send PF', + findBrandInVBank_kindHandle: 'Alleged: kind', }, orchestration: { 'Cosmos Orchestration Account Holder_kindHandle': 'Alleged: kind', @@ -51,9 +61,14 @@ Generated by [AVA](https://avajs.dev). }, }, vows: { + AdminRetriableFlow_kindHandle: 'Alleged: kind', + AdminRetriableFlow_singleton: 'Alleged: AdminRetriableFlow', PromiseWatcher_kindHandle: 'Alleged: kind', VowInternalsKit_kindHandle: 'Alleged: kind', WatchUtils_kindHandle: 'Alleged: kind', + retriableFlowForOutcomeVow: {}, + }, + zoe: { + localTransfer_kindHandle: 'Alleged: kind', }, - zoe: {}, } diff --git a/packages/orchestration/test/examples/snapshots/sendAnywhere.test.ts.snap b/packages/orchestration/test/examples/snapshots/sendAnywhere.test.ts.snap index 785dda987fc272fc94708bed534a963109e78ead..511023e2825d74e8874e039745fa5d636779e3d8 100644 GIT binary patch literal 1150 zcmV-^1cCcORzVGWet?5)ELi zTFuXWaUY8a00000000B6S3PVaMHK$V_O92Ce`1p3E{WkRL31D>L3v0BCtxLTM?!MR zfv!N~-LbQHJ!8#|F+oUh0wGb+fGCiV?g|=cuLA)Ef&!4Pp`fCqph8qs$m{H8clL<9 z0avSe-}lX%H}Ac9zSZk`!XEfHZ!_g8kM+B>-=}@%`kapZL!tbew;hKn`f}}~Jc^k9 zh($`z0oVcXA%LF%{0<;TfF=Q+B*2RVSR!VFnA_b~nXL$kJ{K1kL8>4YNF7Tgw@mUN zMuR-~%vjQ{$67n%uIKuPt><0!%E0B$CgqODLRhu!d92Tz%dM$R(^%SNwvY~!a}aBU z^av1|OVmH&cE=Nwz;q{Ovg||Z^38EKu>6&<2(BcxRbY8EcVejuX&*9QNvd4IXS>DB zh1bNy4_0r*R`YKNHVtp(haB*84yfjV{XFnN9=MwaE*5~73c$w&;Hv`gTLH)$TBvi$ zP+P>hYyeLiz>xvmF@U=U@TUPhVFGWO8r{_C=C>yBy$P5_;DsXaUJ>}FsL@I~tw=1O zXaP4Y;ByQ3!vZdqfI&&4mQ&PsO2GRi;KvfsECV;nz$azkm$F8!>C{|q0k9S{*kUUC z7PQP+X*)xgx5FIBns^s9y6^J7$CTh9;C#eRA~l`mb$9BeD|l89nw>EZi2HmZ>1Z@p z4I~uS(h8|#tVRMUuwIH+M1M~S$+Eh!vZttGSx!+Sq_c2RMa#2F9&`Iy+Gp}Q9WXho zwQda6h)^BsdSl6EkhkNIo+l<9A-BiM7DINBx~_nW zfvk={9OL_K?rcQ6WmUR(tdwwf4v{K|p{H9IsaauWE_{uCO5rDw`laqM?zDC~S@&;* zywt{v5$zbFmwV6U&bp-B+2RN5ln>^MpQ*__wjunX@LSvQ_pa5pZ87GmwJE&$UgL!3 zBUgk?y?>EB!&tBu=mqibP@6iLd(!z6S48I1G>ND%12Cced0$Z{UF- zpLUs&?sR@S%k$N|heRr&){;+H0<9O-jub=JXVVcSSam6I3o_~h>J{Rn} zuUyZcFVsfmB-E=ielV^5S3!v00laB)U6Yjiy}6ER&1Ms$EhRl7`S7b=uSd3UZYgNv zP10(dYAv2>we-O$|4;?EQ~~UYHasnyDpXI6Rylp9p&6#C8X<4RE~Cu2BPK(}l^;xZ zpH+Y_bO$Rb7f2xVbxepn9t@U$R{&Ijr>elaRp7fS(5M01HBGac($vfDLOA;e^GfE9 zl4Pff?f!_I0R9g>JXvWefs`jJ5nspt*Fs1JB*{J{APFGzXqS1fH^V5kj{m^6XiqWO Q@)ecpAKyZ_r{xX+00Dh9%K!iX literal 954 zcmV;r14aBnRzV?K<+(NO9>B>t6 zZm#wv$RCRc00000000A>R!wi*L>PX?Uu$ogk0mK-+7!7Gr%E6pIB`Ln(j`$-B_uR0 zLa3UxXLsH8&a7s}UCOODKmu{=nR4R7iGKhGnm>VrdO`dH4hXFiZ`NZG#r4VZ`#jIQ z^Um|W;~#q6R76Ad^f}XsPFcT8`+eGHiQ;su212W+&*PYC`f2kY8x2e!;uF6EU>Csm z0A2ui3E*D<*9q`00al6EBHmv25sNe-v)7fC6_7=c2FNm2iM2*-5Vu9%_%M^So3d~} z>!yhsgm)7CaG3CToANki1#GdMrmWB6_rqz-&{#cSk&rQy7a%SXvQ2;@98mRyN1aqm z^3b!nkRJ)IC5?0*Ii8Cw3K#@I35VXJO~Dn5g{gdvjmyF9n+x@X~<=Jg|Ug z7Vw7!Y}mkOHt>@T{AmL>9N;4dc;o=zIz~aQazTCK{^kJ34iLD&$1d=-YfwCs()iT{ zUbw(@4;XpC&mQo%2fWoVs11|q+-?AO8o)OV;MjyO81QoRQpF1k#yM`Z<59xf#fj9l z!4-q965dal7Q6tg&)8+8p|iG?OtVY`ubaVUC*wKs9-l}$9$(0jC53BMg~~Rr&IBr8 zvoUr>|4<9b>ZY-AsHtXkb}{V%|IF=cCw-Oi=r-*$d7loMJn4xWbEwt~)uBn6Np=GH zU>?#-#iS$TUZx{4Vn>zJ3bH)QyL4Q9xjaj4!szfW9p@#;9p{+)yfvT+-_E)xj;QT8 zgMNg?ynG!R(YUsk*UwTBwRf|5z(zu|ddn{n^7)*FJ;ivuqw^E6 zO#|*rF-jD>Pjxh?U+k+#VzR?ElbojN6^eT~U-zC)Qgs39=|FeeQqm{HF5Z@xmn*~G zIrl1X&3ncE$_Kvlf!}@OPVp}Ks5F)OKiva&2uce801img5C8xG diff --git a/packages/orchestration/test/examples/snapshots/unbondExample.test.ts.md b/packages/orchestration/test/examples/snapshots/unbondExample.test.ts.md index 9c684aaa5e0b..8d84903d0377 100644 --- a/packages/orchestration/test/examples/snapshots/unbondExample.test.ts.md +++ b/packages/orchestration/test/examples/snapshots/unbondExample.test.ts.md @@ -24,6 +24,86 @@ Generated by [AVA](https://avajs.dev). flowForOutcomeVow: {}, unwrapMap: 'Alleged: weakMapStore', }, + chainHub: { + ChainHub_kindHandle: 'Alleged: kind', + ChainHub_singleton: 'Alleged: ChainHub', + chainInfos: { + agoric: { + chainId: 'agoric-3', + icqEnabled: false, + stakingTokens: [ + { + denom: 'ubld', + }, + ], + }, + omniflixhub: { + chainId: 'omniflixhub-1', + icqEnabled: false, + stakingTokens: [ + { + denom: 'uflix', + }, + ], + }, + stride: { + chainId: 'stride-1', + icqEnabled: false, + stakingTokens: [ + { + denom: 'ustrd', + }, + ], + }, + }, + connectionInfos: { + 'agoric-3_omniflixhub-1': { + client_id: '07-tendermint-73', + counterparty: { + client_id: '07-tendermint-47', + connection_id: 'connection-40', + prefix: { + key_prefix: 'FIXME', + }, + }, + id: 'connection-67', + state: 3, + transferChannel: { + channelId: 'channel-58', + counterPartyChannelId: 'channel-30', + counterPartyPortId: 'transfer', + ordering: 0, + portId: 'transfer', + state: 3, + version: 'ics20-1', + }, + }, + 'agoric-3_stride-1': { + client_id: '07-tendermint-74', + counterparty: { + client_id: '07-tendermint-129', + connection_id: 'connection-118', + prefix: { + key_prefix: 'FIXME', + }, + }, + id: 'connection-68', + state: 3, + transferChannel: { + channelId: 'channel-59', + counterPartyChannelId: 'channel-148', + counterPartyPortId: 'transfer', + ordering: 0, + portId: 'transfer', + state: 3, + version: 'ics20-1', + }, + }, + }, + lookupChainInfo_kindHandle: 'Alleged: kind', + lookupChainsAndConnection_kindHandle: 'Alleged: kind', + lookupConnectionInfo_kindHandle: 'Alleged: kind', + }, contract: { publicFacet_kindHandle: 'Alleged: kind', publicFacet_singleton: 'Alleged: publicFacet', @@ -39,9 +119,14 @@ Generated by [AVA](https://avajs.dev). RemoteChainFacade_kindHandle: 'Alleged: kind', }, vows: { + AdminRetriableFlow_kindHandle: 'Alleged: kind', + AdminRetriableFlow_singleton: 'Alleged: AdminRetriableFlow', PromiseWatcher_kindHandle: 'Alleged: kind', VowInternalsKit_kindHandle: 'Alleged: kind', WatchUtils_kindHandle: 'Alleged: kind', + retriableFlowForOutcomeVow: {}, + }, + zoe: { + localTransfer_kindHandle: 'Alleged: kind', }, - zoe: {}, } diff --git a/packages/orchestration/test/examples/snapshots/unbondExample.test.ts.snap b/packages/orchestration/test/examples/snapshots/unbondExample.test.ts.snap index 90dff347a7304446288687837454c7a52b64a33f..4cd5806388600dcaaf876de0f358df91f4f2a221 100644 GIT binary patch literal 1721 zcmV;q21fZoRzV0hJ4tiYg(vum}mk5pm%LlZ{s&^ zYPVeQ$us}={r^AjUuWJf6%3)RSx=v2QkMo}mZYZCEl#V}s*u*xCyPZY>BG6_y$GWI zBOwyL55N+DR{?wu;3ohc0*n)2Hvt|XK$--SBygbcDAOb%?Z3mr!yqw`5J&=P;>i#% zh(AfLzqe-6g2D1jwSu8rtNHtNxw5A7;y%iY25Z4$vxdRStawMhE>m=*4>C=dMP~Lv zj1y8KKua8^)&|$+4Y6*E&NxINZI$YLU#(zEe(913E={UQTQcG4NMgd&R+%MDDs{na z@ll7^cTB8X_TASUcfF4bRzKdMk3GP74?w)Yf){w!3taF5X&&d*`RKW9FkPBL7pN`$WxI{GCEKWZsv9+vH6R~4Atghs&kOTFO=_aT9&|-3T(iC0Pphpv*|uxzjIQmcRr?6+ zj0>s~7P+2+kT+tfFXhl)Ud81u36jeVW}Hdf2nuGk$R)1^TCuB8UrEf_%!NC zv}{stmHK+rP-DLPXHAoC5O3>WB9UmzTC?A$tO(swzq&y9YEj^cC~zVQoQ^7sM9{Sm zU5o->M1kK_XwtQsj0^!2LketsQ}?cSEiPXBupb_B)Hy8+Q`hYKFF5W;MTP4nLqERS z90MOXNtQJAB5Sq8e;42%9nxGw<>dAihmOf<8@Dy)9HK2;LtP!xBfJ?pz+M$1zU3Hj zGzL5q1Kx=#2NrTg?0gKk7z2Kd0lByWkGkNu#ev;%K#K#5F2dfVRc z)Q(BXc#)YEoy*A`+ikTkIn)l>vyquqYRU~opQocJ)>)n=Z{MNd{8oLbwXb~568^|x zA|actZ*G-x&Wx+{ea2S&`!)K$^UA*8oZQU!5b>0ffRRL3mkxJ#Y2rDS1fEntLn`R` zB=Cv?N+=-T>q+3PB=AKNAStED(yn*lkrXhI0`5-%&!&L0Dd6iA@OKIrNh|cMtAXrE z1M_KMBMrQ#!ne4rT}T6;rGZOnU@8M>8Q_@=a4G|Qno;N@-SmjvOrwPSoUuQ*w68PS z?(5x+>mCJm#k84Glhu(8E4_1MX39>3Le?=*swOMx$9ul>bO$bgDekyfb;5nr+!; z#xB(}cJ8vg?NjPok(0M1OzCJTtqfHtA^Y=?&dZJ5h9VAB`_iJ8M|XES#!O4^?0-RB zvu>Sgj>#)WD%l;W>05X86{@%+RMXQt?O46|AH+(vzIm*oE#CBu8sz_5utLOhIt!f5 zD%Bcs?Rej2fge;@%mpJkAed8N!!Fn@IbceKWn8d_a=;@h>^j$Op{`~ABIBacy7JWu zMzIf^zgAxe`T| zPbM+lrXPz400000000A>R?BYFKomV=J9Y}BY1EX`2gqxL*sx;*p%4nBYSr{1R%qf( z6O+kIG@cO3iXyRw9TE$q_7hll)fIdJQrG+j6^ctzXChEcR@R(z?p)u;aSr!tTn4S^ z;E3r^bH*Y~l@238J5f{W=-{YcrJ_7g-;3t4H0M`j{hXAw0 zEf9CT_L2pfkm2LZ%nV2l!~@A=mRLn%gJcTi#>1|nHO~BvZjFag(|;D~7p+j#SE;CT zHlXE7oU;b2-}U>L5o30f1ya?Snm{;B$SMH_@Dz>qMNsCl7ek*CP&SZ4D;nq+IY}Tn zse&epw4yqcB8Gn@VCR+WMe*q^>*CaYBU!(ISDsqHh6Q}EfFBl6uz{)#9NNIC4JAz55xUoB=*(fUgiyNaDtj+2x