diff --git a/packages/boot/test/orchestration/contract-upgrade.test.ts b/packages/boot/test/orchestration/contract-upgrade.test.ts
index ada1a4a4144..011b66ceb38 100644
--- a/packages/boot/test/orchestration/contract-upgrade.test.ts
+++ b/packages/boot/test/orchestration/contract-upgrade.test.ts
@@ -4,6 +4,8 @@ import type { TestFn } from 'ava';
import { BridgeId } from '@agoric/internal';
import { buildVTransferEvent } from '@agoric/orchestration/tools/ibc-mocks.js';
+import fetchedChainInfo from '@agoric/orchestration/src/fetched-chain-info.js';
+import { withChainCapabilities } from '@agoric/orchestration';
import {
makeWalletFactoryContext,
type WalletFactoryTestContext,
@@ -19,17 +21,13 @@ test.before(async t => {
test.after.always(t => t.context.shutdown?.());
/**
- * This test core-evals a buggy installation of the sendAnywhere contract by
- * giving it a faulty `agoricNames` service with a lookup() function which
- * returns a promise that never resolves.
+ * This test core-evals an installation of the sendAnywhere contract that
+ * initiates an IBC Transfer. Since that goes over a bridge and is tracked
+ * by a vow, we can restart the contract and see that the vow settles. We
+ * can manually trigger a bridge event in the testing context.
*
- * Because the send-anywhere flow requires a lookup(), it waits forever. This
- * gives us a point at which we can upgrade the vat with a working agoricNames
- * and see that the flow continues from that point. (The lookup call is not made
- * directly in a flow, but instead from a host API which uses the retryable
- * helper. As such it tests both the idempotent retry mechanism of retryable on
- * upgrades, and the ability to resume an async-flow for which a host vow
- * settles after an upgrade.)
+ * As such, this demonstrates the ability to resume an async-flow for for which
+ * a host vow settles after an upgrade.
*/
test('resume', async t => {
const {
@@ -44,9 +42,19 @@ test('resume', async t => {
t.log('start sendAnywhere');
await evalProposal(
- buildProposal(
- '@agoric/builders/scripts/testing/start-buggy-sendAnywhere.js',
- ),
+ buildProposal('@agoric/builders/scripts/testing/init-send-anywhere.js', [
+ '--chainInfo',
+ JSON.stringify(withChainCapabilities(fetchedChainInfo)),
+ '--assetInfo',
+ JSON.stringify({
+ uist: {
+ chainName: 'agoric',
+ baseName: 'agoric',
+ baseDenom: 'uist',
+ brandKey: 'Stable',
+ },
+ }),
+ ]),
);
t.log('making offer');
@@ -70,16 +78,9 @@ test('resume', async t => {
// XXX golden test
const getLogged = () =>
- JSON.parse(storage.data.get('published.sendAnywhere.log')!).values;
-
- // This log shows the flow started, but didn't get past the name lookup
- t.deepEqual(getLogged(), ['sending {0} from cosmoshub to cosmos1whatever']);
-
- t.log('upgrade sendAnywhere with fix');
- await evalProposal(
- buildProposal('@agoric/builders/scripts/testing/fix-buggy-sendAnywhere.js'),
- );
+ JSON.parse(storage.data.get('published.send-anywhere.log')!).values;
+ // This log shows the flow started, but didn't get past the IBC Transfer settlement
t.deepEqual(getLogged(), [
'sending {0} from cosmoshub to cosmos1whatever',
'got info for denoms: ibc/FE98AAD68F02F03565E9FA39A5E627946699B2B07115889ED812D8BA639576A9, ibc/toyatom, ibc/toyusdc, ubld, uist',
@@ -87,6 +88,11 @@ test('resume', async t => {
'completed transfer to localAccount',
]);
+ t.log('upgrade sendAnywhere with fix');
+ await evalProposal(
+ buildProposal('@agoric/builders/scripts/testing/upgrade-send-anywhere.js'),
+ );
+
// simulate ibc/MsgTransfer ack from remote chain, enabling `.transfer()` promise
// to resolve
await runInbound(
diff --git a/packages/builders/scripts/testing/start-buggy-sendAnywhere.js b/packages/builders/scripts/testing/start-buggy-sendAnywhere.js
deleted file mode 100644
index 6f5ac66ee1d..00000000000
--- a/packages/builders/scripts/testing/start-buggy-sendAnywhere.js
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * @file This is for use in tests in a3p-integration
- * Unlike most builder scripts, this one includes the proposal exports as well.
- */
-import {
- deeplyFulfilledObject,
- makeTracer,
- NonNullish,
-} from '@agoric/internal';
-import { E, Far } from '@endo/far';
-
-///
-/**
- * @import {Installation} from '@agoric/zoe/src/zoeService/utils.js';
- */
-
-const trace = makeTracer('StartBuggySA', true);
-
-/**
- * @import {start as StartFn} from '@agoric/orchestration/src/examples/send-anywhere.contract.js';
- */
-
-/**
- * @param {BootstrapPowers & {
- * installation: {
- * consume: {
- * sendAnywhere: Installation;
- * };
- * };
- * }} powers
- */
-export const startSendAnywhere = async ({
- consume: {
- agoricNames,
- board,
- chainStorage,
- chainTimerService,
- cosmosInterchainService,
- localchain,
- startUpgradable,
- },
- installation: {
- consume: { sendAnywhere },
- },
- instance: {
- // @ts-expect-error unknown instance
- produce: { sendAnywhere: produceInstance },
- },
-}) => {
- trace(startSendAnywhere.name);
-
- const marshaller = await E(board).getReadonlyMarshaller();
-
- const privateArgs = await deeplyFulfilledObject(
- harden({
- agoricNames,
- localchain,
- marshaller,
- orchestrationService: cosmosInterchainService,
- storageNode: E(NonNullish(await chainStorage)).makeChildNode(
- 'sendAnywhere',
- ),
- timerService: chainTimerService,
- }),
- );
-
- /** @type {import('@agoric/vats').NameHub} */
- // @ts-expect-error intentional fake
- const agoricNamesHangs = Far('agoricNames that hangs', {
- lookup: async () => {
- trace('agoricNames.lookup being called that will never resolve');
- // BUG: this never resolves
- return new Promise(() => {});
- },
- });
-
- const { instance } = await E(startUpgradable)({
- label: 'sendAnywhere',
- installation: sendAnywhere,
- privateArgs: {
- ...privateArgs,
- agoricNames: agoricNamesHangs,
- },
- });
- produceInstance.resolve(instance);
- trace('done');
-};
-harden(startSendAnywhere);
-
-export const getManifestForValueVow = ({ restoreRef }, { sendAnywhereRef }) => {
- trace('sendAnywhereRef', sendAnywhereRef);
- return {
- manifest: {
- [startSendAnywhere.name]: {
- consume: {
- agoricNames: true,
- board: true,
- chainStorage: true,
- chainTimerService: true,
- cosmosInterchainService: true,
- localchain: true,
-
- startUpgradable: true,
- },
- installation: {
- consume: { sendAnywhere: true },
- },
- instance: {
- produce: { sendAnywhere: true },
- },
- },
- },
- installations: {
- sendAnywhere: restoreRef(sendAnywhereRef),
- },
- };
-};
-
-/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */
-export const defaultProposalBuilder = async ({ publishRef, install }) =>
- harden({
- // Somewhat unorthodox, source the exports from this builder module
- sourceSpec: '@agoric/builders/scripts/testing/start-buggy-sendAnywhere.js',
- getManifestCall: [
- 'getManifestForValueVow',
- {
- sendAnywhereRef: publishRef(
- install(
- '@agoric/orchestration/src/examples/send-anywhere.contract.js',
- ),
- ),
- },
- ],
- });
-
-/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').DeployScriptFunction} */
-export default async (homeP, endowments) => {
- // import dynamically so the module can work in CoreEval environment
- const dspModule = await import('@agoric/deploy-script-support');
- const { makeHelpers } = dspModule;
- const { writeCoreEval } = await makeHelpers(homeP, endowments);
- await writeCoreEval(startSendAnywhere.name, defaultProposalBuilder);
-};
diff --git a/packages/builders/scripts/testing/fix-buggy-sendAnywhere.js b/packages/builders/scripts/testing/upgrade-send-anywhere.js
similarity index 81%
rename from packages/builders/scripts/testing/fix-buggy-sendAnywhere.js
rename to packages/builders/scripts/testing/upgrade-send-anywhere.js
index 8daa2dbf516..4acfaf5f8ad 100644
--- a/packages/builders/scripts/testing/fix-buggy-sendAnywhere.js
+++ b/packages/builders/scripts/testing/upgrade-send-anywhere.js
@@ -7,14 +7,14 @@ import {
makeTracer,
NonNullish,
} from '@agoric/internal';
-import { E, Far } from '@endo/far';
+import { E } from '@endo/far';
///
/**
* @import {Installation, Instance} from '@agoric/zoe/src/zoeService/utils.js';
*/
-const trace = makeTracer('FixBuggySA', true);
+const trace = makeTracer('UpgradeSA', true);
/**
* @import {start as StartFn} from '@agoric/orchestration/src/examples/send-anywhere.contract.js';
@@ -30,7 +30,7 @@ const trace = makeTracer('FixBuggySA', true);
* }} powers
* @param {...any} rest
*/
-export const fixSendAnywhere = async (
+export const upgradeSendAnywhere = async (
{
consume: {
agoricNames,
@@ -45,7 +45,7 @@ export const fixSendAnywhere = async (
},
{ options: { sendAnywhereRef } },
) => {
- trace(fixSendAnywhere.name);
+ trace(upgradeSendAnywhere.name);
const saInstance = await instances.consume.sendAnywhere;
trace('saInstance', saInstance);
@@ -53,28 +53,24 @@ export const fixSendAnywhere = async (
const marshaller = await E(board).getReadonlyMarshaller();
- // This apparently pointless wrapper is to maintain structural parity
- // with the buggy core-eval's wrapper to make lookup() hang.
- const agoricNamesResolves = Far('agoricNames that resolves', {
- lookup: async (...args) => {
- return E(agoricNames).lookup(...args);
- },
- });
-
const privateArgs = await deeplyFulfilledObject(
harden({
- agoricNames: agoricNamesResolves,
+ agoricNames,
localchain,
marshaller,
orchestrationService: cosmosInterchainService,
storageNode: E(NonNullish(await chainStorage)).makeChildNode(
- 'sendAnywhere',
+ 'send-anywhere',
),
timerService: chainTimerService,
+ // undefined so `registerKnownChainsAndAssets` does not run again
+ chainInfo: undefined,
+ assetInfo: undefined,
}),
);
trace('upgrading...');
+ trace('ref', sendAnywhereRef);
await E(saKit.adminFacet).upgradeContract(
sendAnywhereRef.bundleID,
privateArgs,
@@ -82,13 +78,13 @@ export const fixSendAnywhere = async (
trace('done');
};
-harden(fixSendAnywhere);
+harden(upgradeSendAnywhere);
export const getManifestForValueVow = ({ restoreRef }, { sendAnywhereRef }) => {
console.log('sendAnywhereRef', sendAnywhereRef);
return {
manifest: {
- [fixSendAnywhere.name]: {
+ [upgradeSendAnywhere.name]: {
consume: {
agoricNames: true,
board: true,
@@ -120,7 +116,7 @@ export const getManifestForValueVow = ({ restoreRef }, { sendAnywhereRef }) => {
export const defaultProposalBuilder = async ({ publishRef, install }) =>
harden({
// Somewhat unorthodox, source the exports from this builder module
- sourceSpec: '@agoric/builders/scripts/testing/fix-buggy-sendAnywhere.js',
+ sourceSpec: '@agoric/builders/scripts/testing/upgrade-send-anywhere.js',
getManifestCall: [
'getManifestForValueVow',
{
@@ -139,5 +135,5 @@ export default async (homeP, endowments) => {
const dspModule = await import('@agoric/deploy-script-support');
const { makeHelpers } = dspModule;
const { writeCoreEval } = await makeHelpers(homeP, endowments);
- await writeCoreEval(fixSendAnywhere.name, defaultProposalBuilder);
+ await writeCoreEval(upgradeSendAnywhere.name, defaultProposalBuilder);
};