Skip to content

Commit

Permalink
higher order contracts: withOrchestration (Agoric#9668)
Browse files Browse the repository at this point in the history
_incidental_

## Description

`provideOrchestration` sought to bundle up all the boilerplate. @mhofman suggested an even cleaner bundling: `withOrchestration`. This lets the contract function ignore the privateArgs powers entirely and get a zone instead of baggage.

This makes that change, which required a name for the orchestration tools being provided. `OrchestrationTools` was the natural name but was used by a service for ICA accounts. @0xpatrickdev had some ideas for improving those names so this incorporates that as well.

It also rearranges the zone as @dtribble had in Agoric#9657


### Security Considerations
Requires handing full privateArgs to the `withOrchestration` helper. It's not a great habit to hand everything out of module scope but this is a well vetted utility. Eventually we expect to provide some of these abilities on the ZCF.

### Scaling Considerations
none

### Documentation Considerations
none

### Testing Considerations
CI. 

### Upgrade Considerations
Not yet deployed
  • Loading branch information
mergify[bot] authored Jul 9, 2024
2 parents 023e19f + 1c1560a commit b196804
Show file tree
Hide file tree
Showing 25 changed files with 248 additions and 236 deletions.
10 changes: 5 additions & 5 deletions packages/boot/test/bootstrapTests/vat-orchestration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
MsgDelegate,
MsgDelegateResponse,
} from '@agoric/cosmic-proto/cosmos/staking/v1beta1/tx.js';
import type { OrchestrationService } from '@agoric/orchestration';
import type { CosmosInterchainService } from '@agoric/orchestration';
import { decodeBase64 } from '@endo/base64';
import { M, matches } from '@endo/patterns';
import {
Expand Down Expand Up @@ -187,7 +187,7 @@ test.skip('Query connection can be created', async t => {
runUtils: { EV },
} = t.context;

type Powers = { orchestration: OrchestrationService };
type Powers = { orchestration: CosmosInterchainService };
const contract = async ({ orchestration }) => {
const connection =
await EV(orchestration).provideICQConnection('connection-0');
Expand All @@ -201,7 +201,7 @@ test.skip('Query connection can be created', async t => {

// core eval context
{
const orchestration: OrchestrationService =
const orchestration: CosmosInterchainService =
await EV.vat('bootstrap').consumeItem('orchestration');
await contract({ orchestration });
}
Expand All @@ -213,7 +213,7 @@ test.skip('Query connection can send a query', async t => {
runUtils: { EV },
} = t.context;

type Powers = { orchestration: OrchestrationService };
type Powers = { orchestration: CosmosInterchainService };
const contract = async ({ orchestration }) => {
const queryConnection =
await EV(orchestration).provideICQConnection('connection-0');
Expand Down Expand Up @@ -255,7 +255,7 @@ test.skip('Query connection can send a query', async t => {

// core eval context
{
const orchestration: OrchestrationService =
const orchestration: CosmosInterchainService =
await EV.vat('bootstrap').consumeItem('orchestration');
await contract({ orchestration });
}
Expand Down
2 changes: 1 addition & 1 deletion packages/orchestration/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
/// <reference types="@agoric/zoe/exported" />

export * from './src/types.js';
export * from './src/service.js';
export * from './src/exos/cosmos-interchain-service.js';
export * from './src/typeGuards.js';
39 changes: 22 additions & 17 deletions packages/orchestration/src/examples/sendAnywhere.contract.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import { makeStateRecord } from '@agoric/async-flow';
import { AmountShape } from '@agoric/ertp';
import { heapVowE } from '@agoric/vow/vat.js';
import { withdrawFromSeat } from '@agoric/zoe/src/contractSupport/zoeHelpers.js';
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js';
import { M, mustMatch } from '@endo/patterns';
import { E } from '@endo/far';
import { heapVowE } from '@agoric/vow/vat.js';
import { makeStateRecord } from '@agoric/async-flow';
import { AmountShape } from '@agoric/ertp';
import { CosmosChainInfoShape } from '../typeGuards.js';
import { provideOrchestration } from '../utils/start-helper.js';
import { M, mustMatch } from '@endo/patterns';
import { makeResumableAgoricNamesHack } from '../exos/agoric-names-tools.js';
import { CosmosChainInfoShape } from '../typeGuards.js';
import { withOrchestration } from '../utils/start-helper.js';

const { entries } = Object;

/**
* @import {Baggage} from '@agoric/vat-data';
* @import {TimerService} from '@agoric/time';
* @import {LocalChain} from '@agoric/vats/src/localchain.js';
* @import {NameHub} from '@agoric/vats';
* @import {Remote} from '@agoric/vow';
* @import {Zone} from '@agoric/zone';
* @import {CosmosChainInfo, IBCConnectionInfo} from '../cosmos-api';
* @import {OrchestrationService} from '../service.js';
* @import {CosmosInterchainService} from '../exos/cosmos-interchain-service.js';
* @import {Orchestrator} from '../types.js'
* @import {OrchestrationTools} from '../utils/start-helper.js';
* @import {OrchestrationAccount} from '../orchestration-api.js'
*/

/**
* @typedef {{
* localchain: Remote<LocalChain>;
* orchestrationService: Remote<OrchestrationService>;
* orchestrationService: Remote<CosmosInterchainService>;
* storageNode: Remote<StorageNode>;
* timerService: Remote<TimerService>;
* agoricNames: Remote<NameHub>;
Expand Down Expand Up @@ -89,19 +90,21 @@ export const SingleAmountRecord = M.and(
);

/**
* Orchestration contract to be wrapped by withOrchestration for Zoe
*
* @param {ZCF} zcf
* @param {OrchestrationPowers & {
* marshaller: Marshaller;
* }} privateArgs
* @param {Baggage} baggage
* @param {Zone} zone
* @param {OrchestrationTools} tools
*/
export const start = async (zcf, privateArgs, baggage) => {
const { chainHub, orchestrate, vowTools, zone } = provideOrchestration(
zcf,
baggage,
privateArgs,
privateArgs.marshaller,
);
const contract = async (
zcf,
privateArgs,
zone,
{ chainHub, orchestrate, vowTools },
) => {
const agoricNamesTools = makeResumableAgoricNamesHack(zone, {
agoricNames: privateArgs.agoricNames,
vowTools,
Expand Down Expand Up @@ -171,3 +174,5 @@ export const start = async (zcf, privateArgs, baggage) => {

return { publicFacet, creatorFacet };
};

export const start = withOrchestration(contract);
13 changes: 9 additions & 4 deletions packages/orchestration/src/examples/stakeIca.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const trace = makeTracer('StakeIca');
* @import {Baggage} from '@agoric/vat-data';
* @import {IBCConnectionID} from '@agoric/vats';
* @import {TimerService} from '@agoric/time';
* @import {ICQConnection, OrchestrationService} from '../types.js';
* @import {ICQConnection, CosmosInterchainService} from '../types.js';
*/

/** @type {ContractMeta<typeof start>} */
Expand All @@ -30,7 +30,7 @@ export const meta = harden({
icqEnabled: M.boolean(),
},
privateArgsShape: {
orchestration: M.remotable('orchestration'),
cosmosInterchainService: M.remotable('cosmosInterchainService'),
storageNode: StorageNodeShape,
marshaller: M.remotable('marshaller'),
timer: TimerServiceShape,
Expand All @@ -51,7 +51,7 @@ export const privateArgsShape = meta.privateArgsShape;
/**
* @param {ZCF<StakeIcaTerms>} zcf
* @param {{
* orchestration: OrchestrationService;
* cosmosInterchainService: CosmosInterchainService;
* storageNode: StorageNode;
* marshaller: Marshaller;
* timer: TimerService;
Expand All @@ -66,7 +66,12 @@ export const start = async (zcf, privateArgs, baggage) => {
bondDenom,
icqEnabled,
} = zcf.getTerms();
const { orchestration, marshaller, storageNode, timer } = privateArgs;
const {
cosmosInterchainService: orchestration,
marshaller,
storageNode,
timer,
} = privateArgs;

const zone = makeDurableZone(baggage);

Expand Down
68 changes: 25 additions & 43 deletions packages/orchestration/src/examples/swapExample.contract.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { StorageNodeShape } from '@agoric/internal';
import { TimerServiceShape } from '@agoric/time';
import { withdrawFromSeat } from '@agoric/zoe/src/contractSupport/zoeHelpers.js';
import { Far } from '@endo/far';
import { deeplyFulfilled } from '@endo/marshal';
import { M, objectMap } from '@endo/patterns';
import { orcUtils } from '../utils/orc.js';
import { provideOrchestration } from '../utils/start-helper.js';
import { withOrchestration } from '../utils/start-helper.js';

/**
* @import {Orchestrator, IcaAccount, CosmosValidatorAddress} from '../types.js'
* @import {TimerService} from '@agoric/time';
* @import {LocalChain} from '@agoric/vats/src/localchain.js';
* @import {Remote} from '@agoric/internal';
* @import {OrchestrationService} from '../service.js';
* @import {Baggage} from '@agoric/vat-data'
* @import {CosmosInterchainService} from '../exos/cosmos-interchain-service.js';
* @import {NameHub} from '@agoric/vats';
* @import {Zone} from '@agoric/zone';
* @import {OrchestrationTools} from '../utils/start-helper.js';
*/

/**
Expand Down Expand Up @@ -90,40 +90,21 @@ export const makeNatAmountShape = (brand, min) =>
harden({ brand, value: min ? M.gte(min) : M.nat() });

/**
* Orchestration contract to be wrapped by withOrchestration for Zoe
*
* @param {ZCF} zcf
* @param {{
* agoricNames: Remote<NameHub>;
* localchain: Remote<LocalChain>;
* orchestrationService: Remote<OrchestrationService>;
* orchestrationService: Remote<CosmosInterchainService>;
* storageNode: Remote<StorageNode>;
* timerService: Remote<TimerService>;
* marshaller: Marshaller;
* }} privateArgs
* @param {Baggage} baggage
* @param {Zone} zone
* @param {OrchestrationTools} tools
*/
export const start = async (zcf, privateArgs, baggage) => {
const {
agoricNames,
localchain,
orchestrationService,
storageNode,
timerService,
marshaller,
} = privateArgs;

const { orchestrate } = provideOrchestration(
zcf,
baggage,
{
agoricNames,
localchain,
orchestrationService,
storageNode,
timerService,
},
marshaller,
);

const contract = async (zcf, privateArgs, zone, { orchestrate }) => {
const { brands } = zcf.getTerms();

/** deprecated historical example */
Expand All @@ -135,21 +116,22 @@ export const start = async (zcf, privateArgs, baggage) => {
*/
const swapAndStakeHandler = orchestrate('LSTTia', { zcf }, stackAndSwapFn);

const makeSwapAndStakeInvitation = () =>
zcf.makeInvitation(
swapAndStakeHandler,
'Swap for TIA and stake',
undefined,
harden({
give: { Stable: makeNatAmountShape(brands.Stable, 1n) },
want: {}, // XXX ChainAccount Ownable?
exit: M.any(),
}),
);

const publicFacet = Far('SwapAndStake Public Facet', {
makeSwapAndStakeInvitation,
const publicFacet = zone.exo('publicFacet', undefined, {
makeSwapAndStakeInvitation() {
return zcf.makeInvitation(
swapAndStakeHandler,
'Swap for TIA and stake',
undefined,
harden({
give: { Stable: makeNatAmountShape(brands.Stable, 1n) },
want: {}, // XXX ChainAccount Ownable?
exit: M.any(),
}),
);
},
});

return harden({ publicFacet });
};

export const start = withOrchestration(contract);
69 changes: 26 additions & 43 deletions packages/orchestration/src/examples/unbondExample.contract.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Far } from '@endo/far';
import { M } from '@endo/patterns';
import { provideOrchestration } from '../utils/start-helper.js';
import { withOrchestration } from '../utils/start-helper.js';

/**
* @import {Orchestrator, IcaAccount, CosmosValidatorAddress} from '../types.js'
Expand All @@ -9,7 +8,9 @@ import { provideOrchestration } from '../utils/start-helper.js';
* @import {LocalChain} from '@agoric/vats/src/localchain.js';
* @import {NameHub} from '@agoric/vats';
* @import {Remote} from '@agoric/internal';
* @import {OrchestrationService} from '../service.js';
* @import {Zone} from '@agoric/zone';
* @import {CosmosInterchainService} from '../exos/cosmos-interchain-service.js';
* @import {OrchestrationTools} from '../utils/start-helper.js';
*/

/**
Expand Down Expand Up @@ -43,63 +44,45 @@ const unbondAndLiquidStakeFn = async (orch, { zcf }, _seat, _offerArgs) => {
};

/**
* Orchestration contract to be wrapped by withOrchestration for Zoe
*
* @param {ZCF} zcf
* @param {{
* agoricNames: Remote<NameHub>;
* localchain: Remote<LocalChain>;
* orchestrationService: Remote<OrchestrationService>;
* orchestrationService: Remote<CosmosInterchainService>;
* storageNode: Remote<StorageNode>;
* marshaller: Marshaller;
* timerService: Remote<TimerService>;
* }} privateArgs
* @param {Baggage} baggage
* @param {Zone} zone
* @param {OrchestrationTools} tools
*/
export const start = async (zcf, privateArgs, baggage) => {
const {
agoricNames,
localchain,
orchestrationService,
storageNode,
marshaller,
timerService,
} = privateArgs;

const { orchestrate } = provideOrchestration(
zcf,
baggage,
{
agoricNames,
localchain,
orchestrationService,
storageNode,
timerService,
},
marshaller,
);

const contract = async (zcf, privateArgs, zone, { orchestrate }) => {
/** @type {OfferHandler} */
const unbondAndLiquidStake = orchestrate(
'LSTTia',
{ zcf },
unbondAndLiquidStakeFn,
);

const makeUnbondAndLiquidStakeInvitation = () =>
zcf.makeInvitation(
unbondAndLiquidStake,
'Unbond and liquid stake',
undefined,
harden({
// Nothing to give; the funds come from undelegating
give: {},
want: {}, // XXX ChainAccount Ownable?
exit: M.any(),
}),
);

const publicFacet = Far('SwapAndStake Public Facet', {
makeUnbondAndLiquidStakeInvitation,
const publicFacet = zone.exo('publicFacet', undefined, {
makeUnbondAndLiquidStakeInvitation() {
return zcf.makeInvitation(
unbondAndLiquidStake,
'Unbond and liquid stake',
undefined,
harden({
// Nothing to give; the funds come from undelegating
give: {},
want: {}, // XXX ChainAccount Ownable?
exit: M.any(),
}),
);
},
});

return harden({ publicFacet });
};

export const start = withOrchestration(contract);
Loading

0 comments on commit b196804

Please sign in to comment.