Skip to content

Commit

Permalink
feat(orchestration): icqConnectionKit returns unwrapped vows
Browse files Browse the repository at this point in the history
- refs: #9449
  • Loading branch information
0xpatrickdev committed Jun 4, 2024
1 parent ceec1d5 commit 5d7e4b8
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 19 deletions.
32 changes: 24 additions & 8 deletions packages/orchestration/src/exos/icqConnectionKit.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/** @file ICQConnection Exo */
import { NonNullish } from '@agoric/assert';
import { makeTracer } from '@agoric/internal';
import { V as E } from '@agoric/vow/vat.js';
import { E } from '@endo/far';
import { M } from '@endo/patterns';
import { makeQueryPacket, parseQueryPacket } from '../utils/packet.js';
import { ConnectionHandlerI } from '../typeGuards.js';

/**
* @import {Zone} from '@agoric/base-zone';
* @import {Connection, Port} from '@agoric/network';
* @import {Remote} from '@agoric/vow';
* @import {Remote, VowTools} from '@agoric/vow';
* @import {JsonSafe} from '@agoric/cosmic-proto';
* @import {RequestQuery, ResponseQuery} from '@agoric/cosmic-proto/tendermint/abci/types.js';
* @import {LocalIbcAddress, RemoteIbcAddress} from '@agoric/vats/tools/ibc-utils.js';
Expand All @@ -29,6 +29,12 @@ export const ICQConnectionI = M.interface('ICQConnection', {
query: M.call(M.arrayOf(ICQMsgShape)).returns(M.promise()),
});

const HandleQueryWatcherI = M.interface('HandleQueryWatcher', {
onFulfilled: M.call(M.string())
.optional(M.arrayOf(M.undefined())) // does not need watcherContext
.returns(M.arrayOf(M.record())),
});

/**
* @typedef {{
* port: Port;
Expand All @@ -52,11 +58,16 @@ export const ICQConnectionI = M.interface('ICQConnection', {
* sending queries and handling connection events.
*
* @param {Zone} zone
* @param {VowTools} vowTools
*/
export const prepareICQConnectionKit = zone =>
export const prepareICQConnectionKit = (zone, { watch, when }) =>
zone.exoClassKit(
'ICQConnectionKit',
{ connection: ICQConnectionI, connectionHandler: ConnectionHandlerI },
{
connection: ICQConnectionI,
handleQueryWatcher: HandleQueryWatcherI,
connectionHandler: ConnectionHandlerI,
},
/**
* @param {Port} port
*/
Expand Down Expand Up @@ -89,13 +100,18 @@ export const prepareICQConnectionKit = zone =>
query(msgs) {
const { connection } = this.state;
if (!connection) throw Fail`connection not available`;
return E.when(
E(connection).send(makeQueryPacket(msgs)),
// if parseTxPacket cannot find a `result` key, it throws
ack => parseQueryPacket(ack),
return when(
watch(
E(connection).send(makeQueryPacket(msgs)),
this.facets.handleQueryWatcher,
),
);
},
},
handleQueryWatcher: {
/** @param {string} ack packet acknowledgement string */
onFulfilled: ack => parseQueryPacket(ack),
},
connectionHandler: {
/**
* @param {Remote<Connection>} connection
Expand Down
12 changes: 8 additions & 4 deletions packages/orchestration/src/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
* @import {Remote} from '@agoric/internal';
* @import {Port, PortAllocator} from '@agoric/network';
* @import {IBCConnectionID} from '@agoric/vats';
* @import {VowTools} from '@agoric/vow';
* @import {ICQConnection, IcaAccount, ICQConnectionKit} from './types.js';
*/

Expand Down Expand Up @@ -104,7 +105,7 @@ const prepareOrchestrationKit = (
},
async allocateICQControllerPort() {
const portAllocator = getPower(this.state.powers, 'portAllocator');
return E(portAllocator).allocateICAControllerPort();
return E(portAllocator).allocateICQControllerPort();
},
},
public: {
Expand Down Expand Up @@ -163,10 +164,13 @@ const prepareOrchestrationKit = (
},
);

/** @param {Zone} zone */
export const prepareOrchestrationTools = zone => {
/**
* @param {Zone} zone
* @param {VowTools} vowTools
*/
export const prepareOrchestrationTools = (zone, vowTools) => {
const makeChainAccountKit = prepareChainAccountKit(zone);
const makeICQConnectionKit = prepareICQConnectionKit(zone);
const makeICQConnectionKit = prepareICQConnectionKit(zone, vowTools);
const makeOrchestrationKit = prepareOrchestrationKit(
zone,
makeChainAccountKit,
Expand Down
3 changes: 3 additions & 0 deletions packages/orchestration/src/vat-orchestration.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { Far } from '@endo/far';
import { prepareVowTools } from '@agoric/vow/vat.js';
import { makeDurableZone } from '@agoric/zone/durable.js';
import { prepareOrchestrationTools } from './service.js';

/** @import {OrchestrationPowers} from './service.js' */

export const buildRootObject = (_vatPowers, _args, baggage) => {
const zone = makeDurableZone(baggage);
const vowTools = prepareVowTools(zone.subZone('VowTools'));
const { makeOrchestrationKit } = prepareOrchestrationTools(
zone.subZone('orchestration'),
vowTools,
);

return Far('OrchestrationVat', {
Expand Down
11 changes: 6 additions & 5 deletions packages/orchestration/test/network-fakes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,19 @@ export const prepareProtocolHandler = (
};

export const fakeNetworkEchoStuff = (zone: Zone) => {
const powers = prepareVowTools(zone);
const { makeVowKit, when } = powers;
const vowTools = prepareVowTools(zone);
const { makeVowKit, when } = vowTools;

const makeNetworkProtocol = prepareNetworkProtocol(zone, powers);
const makeNetworkProtocol = prepareNetworkProtocol(zone, vowTools);
const makeEchoConnectionHandler = prepareEchoConnectionKit(zone);
const makeProtocolHandler = prepareProtocolHandler(
zone,
makeEchoConnectionHandler,
powers,
vowTools,
);
const protocol = makeNetworkProtocol(makeProtocolHandler());

const makePortAllocator = preparePortAllocator(zone, powers);
const makePortAllocator = preparePortAllocator(zone, vowTools);
const portAllocator = makePortAllocator({ protocol });

return {
Expand All @@ -113,5 +113,6 @@ export const fakeNetworkEchoStuff = (zone: Zone) => {
portAllocator,
protocol,
when,
vowTools,
};
};
50 changes: 50 additions & 0 deletions packages/orchestration/test/service.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js';
import { toRequestQueryJson } from '@agoric/cosmic-proto';
import { QueryBalanceRequest } from '@agoric/cosmic-proto/cosmos/bank/v1beta1/query.js';
import { E } from '@endo/far';
import { commonSetup } from './supports.js';

test('makeICQConnection returns an ICQConnection', async t => {
const {
bootstrap: { orchestration },
} = await commonSetup(t);

const CONNECTION_ID = 'connection-0';

const icqConnection =
await E(orchestration).provideICQConnection(CONNECTION_ID);
const [localAddr, remoteAddr] = await Promise.all([
E(icqConnection).getLocalAddress(),
E(icqConnection).getRemoteAddress(),
]);
t.log(icqConnection, {
localAddr,
remoteAddr,
});
t.regex(localAddr, /ibc-port\/icqcontroller-\d+/);
t.regex(
remoteAddr,
new RegExp(`/ibc-hop/${CONNECTION_ID}`),
'remote address contains provided connectionId',
);
t.regex(
remoteAddr,
/icqhost\/unordered\/icq-1/,
'remote address contains icqhost port, unordered ordering, and icq-1 version string',
);

await t.throwsAsync(
E(icqConnection).query([
toRequestQueryJson(
QueryBalanceRequest.toProtoMsg({
address: 'cosmos1test',
denom: 'uatom',
}),
),
]),
{ message: /"data":"(.*)"memo":""/ },
'TODO do not use echo connection',
);
});

test.todo('makeAccount');
8 changes: 6 additions & 2 deletions packages/orchestration/test/supports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@ export const commonSetup = async t => {
sequence: false,
});

const { portAllocator, vowTools } = fakeNetworkEchoStuff(
rootZone.subZone('network'),
);

const { makeOrchestrationKit } = prepareOrchestrationTools(
rootZone.subZone('orchestration'),
vowTools,
);

const { portAllocator } = fakeNetworkEchoStuff(rootZone.subZone('network'));
const { public: orchestration } = makeOrchestrationKit({ portAllocator });

return {
Expand All @@ -62,6 +65,7 @@ export const commonSetup = async t => {
orchestration,
rootZone,
storage,
vowTools,
},
brands: {
// TODO consider omitting `issuer` to prevent minting, which the bank can't observe
Expand Down
2 changes: 2 additions & 0 deletions packages/vow/src/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ export const prepareVowTools = (zone, powers = {}) => {
return harden({ when, watch, makeVowKit, allVows });
};
harden(prepareVowTools);

/** @typedef { ReturnType<typeof prepareVowTools>} VowTools */

0 comments on commit 5d7e4b8

Please sign in to comment.