Skip to content

Commit

Permalink
BridgeMessage types (#8544)
Browse files Browse the repository at this point in the history
_incidental_

## Description

Define a union type for for BridgeMessage that a `fromBridge` handler can narrow.

That revealed an inert bug in `nonce` handling which this also fixes.

### Security Considerations

none

### Scaling Considerations

none

### Documentation Considerations

none

### Testing Considerations

CI suffices

### Upgrade Considerations

technically affects runtime of vat-bank by correcting the `nonce` handling. But since that case isn't encountered in production I think it's okay to land this and let it be included in whatever future deployment in which that vat is upgraded.
  • Loading branch information
mergify[bot] authored Jan 21, 2025
2 parents b1998a7 + 6da7328 commit 785e426
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 9 deletions.
49 changes: 49 additions & 0 deletions packages/cosmic-swingset/src/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { QueuedActionType } from '@agoric/internal/src/action-types.js';
import type {
CoreEval,
CoreEvalSDKType,
} from '@agoric/cosmic-proto/agoric/swingset/swingset.js';

// TODO move `walletFlags.js` from @agoric/vats to @agoric/cosmic-proto
type PowerFlag = 'SMART_WALLET' | 'REMOTE_WALLET';

// NB: keep these manually synced until we build these types out of the Golang
// structs or use some other shared type truth
// https://github.com/Agoric/agoric-sdk/issues/8545

interface ActionContext<T extends Uppercase<string>> {
type: T;
blockHeight: string;
blockTime: string;
}

/**
* @see coreEvalAction in proposal.go
*/
export type CoreEvalAction = ActionContext<'CORE_EVAL'> & {
evals: CoreEvalSDKType[];
};

/**
* @see provisionAction in msg_server.go
*/
export type PleaseProvisionAction = ActionContext<'PLEASE_PROVISION'> & {
address: string;
nickname: string;
powerFlags: PowerFlag[];
submitter: string;
autoProvision: boolean;
};

/**
* @see VbankBalanceUpdate in vbank.go
*/
export type VbankBalanceUpdateAction = ActionContext<'VBANK_BALANCE_UPDATE'> & {
nonce: string;
updated: Array<{ address: string; denom: string; amount: string }>;
};

export type BridgeMessage =
| CoreEvalAction
| PleaseProvisionAction
| VbankBalanceUpdateAction;
2 changes: 2 additions & 0 deletions packages/cosmic-swingset/src/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Empty JS file to correspond with types.d.ts
export {};
3 changes: 3 additions & 0 deletions packages/cosmic-swingset/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// This file can contain .js-specific Typescript compiler config.
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"skipLibCheck": false
},
"include": [
"calc-*.js",
"src/**/*.js",
Expand Down
11 changes: 9 additions & 2 deletions packages/inter-protocol/src/provisionPoolKit.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import {
import { InstanceHandleShape } from '@agoric/zoe/src/typeGuards.js';
import { isUpgradeDisconnection } from '@agoric/internal/src/upgrade-api.js';

/**
* @import {BridgeMessage} from '@agoric/cosmic-swingset/src/types.js';
*/

const trace = makeTracer('ProvPool');

const FIRST_UPPER_KEYWORD = /^[A-Z][a-zA-Z0-9_$]*$/;
Expand Down Expand Up @@ -88,11 +92,14 @@ export const prepareBridgeProvisionTool = zone =>
forHandler,
}),
{
/** @param {BridgeMessage} obj */
async fromBridge(obj) {
obj.type === 'PLEASE_PROVISION' ||
Fail`Unrecognized request ${obj.type}`;
if (obj.type !== 'PLEASE_PROVISION')
throw Fail`Unrecognized request ${obj.type}`;
trace('PLEASE_PROVISION', obj);
const { address, powerFlags } = obj;
// XXX expects powerFlags to be an array, but if it's a string then
// this allows a string that has 'SMART_WALLET' in it.
powerFlags.includes(PowerFlags.SMART_WALLET) ||
Fail`missing SMART_WALLET in powerFlags`;

Expand Down
14 changes: 12 additions & 2 deletions packages/inter-protocol/test/provisionPool.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,13 @@ test('makeBridgeProvisionTool handles duplicate requests', async t => {
t.log('1st request to provision a SMART_WALLET for', address);
await handler.fromBridge({
type: 'PLEASE_PROVISION',
blockHeight: '123',
blockTime: '1737432662',
address,
powerFlags: PowerFlags.SMART_WALLET,
autoProvision: true,
nickname: 'test',
powerFlags: [PowerFlags.SMART_WALLET],
submitter: address,
});

t.deepEqual(
Expand All @@ -394,8 +399,13 @@ test('makeBridgeProvisionTool handles duplicate requests', async t => {
t.log('2nd request to provision a SMART_WALLET for', address);
await handler.fromBridge({
type: 'PLEASE_PROVISION',
blockHeight: '123',
blockTime: '1737432662',
address,
powerFlags: PowerFlags.SMART_WALLET,
autoProvision: true,
nickname: 'test',
powerFlags: [PowerFlags.SMART_WALLET],
submitter: address,
});
t.is(
myDepositFacet,
Expand Down
7 changes: 6 additions & 1 deletion packages/vats/src/core/chain-behaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import { BASIC_BOOTSTRAP_PERMITS } from './basic-behaviors.js';
import { agoricNamesReserved, callProperties, extractPowers } from './utils.js';
import { makeScopedBridge } from '../bridge.js';

/**
* @import {BridgeMessage} from '@agoric/cosmic-swingset/src/types.js';
*/

const { keys } = Object;

/**
Expand Down Expand Up @@ -57,10 +61,10 @@ export const bridgeCoreEval = async allPowers => {

// Register a coreEval handler over the bridge.
const handler = Far('coreHandler', {
/** @param {BridgeMessage} obj */
async fromBridge(obj) {
switch (obj.type) {
case 'CORE_EVAL': {
/** @type {import('@agoric/cosmic-proto/swingset/swingset.js').CoreEvalProposalSDKType} */
const { evals } = obj;
return Promise.all(
evals.map(({ json_permits: jsonPermit, js_code: code }) =>
Expand Down Expand Up @@ -151,6 +155,7 @@ export const bridgeProvisioner = async ({
// Register a provisioning handler over the bridge.
const handler = provisioning
? Far('provisioningHandler', {
/** @param {BridgeMessage} obj */
async fromBridge(obj) {
switch (obj.type) {
case 'PLEASE_PROVISION': {
Expand Down
9 changes: 5 additions & 4 deletions packages/vats/src/vat-bank.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
/**
* @import {Guarded} from '@endo/exo';
* @import {Passable, RemotableObject} from '@endo/pass-style';
* @import {VirtualPurseController} from './virtual-purse.js';
* @import {BridgeMessage} from '@agoric/cosmic-swingset/src/types.js';
*/

const { VirtualPurseControllerI } = makeVirtualPurseKitIKit();
Expand Down Expand Up @@ -186,12 +186,13 @@ const prepareBankChannelHandler = zone =>
/** @param {MapStore<string, MapStore<string, BalanceUpdater>>} denomToAddressUpdater */
denomToAddressUpdater => ({ denomToAddressUpdater }),
{
/** @param {BridgeMessage} obj */
async fromBridge(obj) {
switch (obj && obj.type) {
switch (obj?.type) {
case 'VBANK_BALANCE_UPDATE': {
const { denomToAddressUpdater } = this.state;
for (const update of obj.updated) {
const { address, denom, amount: value, nonce } = update;
const { address, denom, amount } = update;
/** @type {BalanceUpdater | undefined} */
let updater;
try {
Expand All @@ -204,7 +205,7 @@ const prepareBankChannelHandler = zone =>
}
if (updater) {
try {
updater.update(value, nonce);
updater.update(amount, obj.nonce);
} catch (e) {
// ??? Is this an invariant that should complain louder?

Expand Down

0 comments on commit 785e426

Please sign in to comment.