Skip to content

Commit

Permalink
fixes to chainConnection key and vstorage (#9486)
Browse files Browse the repository at this point in the history
refs: #9063
closes: #8879

## Description

Fast follow on #9376

Tests that uncovered that the JSON.stringify encoding is not a valid
vstorage key. There's one character that can be used as a separator `_`,
the only vstorage valid char that's not a chain-id valid char. (vstorage
chars are superset of chain id chars)

Also fixes the chain_id half of the connection key, which had been chain
name.

Also adds a cache to chain info writer so it doesn't write entries that
exist and haven't changed.

Some misc test supports as well.

### Security Considerations

none

### Scaling Considerations

none

### Documentation Considerations

Eventually we'll document these new vstorage nodes, but probably by just
pointing to some snapshots.

### Testing Considerations

The A3P test checks that it works through agd CLI.

### Upgrade Considerations

not yet released
  • Loading branch information
mergify[bot] authored Jun 12, 2024
2 parents 4687f0d + 6f74158 commit 1d94913
Show file tree
Hide file tree
Showing 13 changed files with 654 additions and 167 deletions.
10 changes: 3 additions & 7 deletions a3p-integration/proposals/b:enable-orchestration/initial.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,9 @@ test('chain info', async t => {
t.like(chain, { chainId: 'cosmoshub-4' });
});

test.failing('chain connection', async t => {
// FIXME encoding
// message: `Command failed with exit code 1: agd query vstorage data --output json published.agoricNames.chainConnection.["agoriclocal","cosmoshub-4"] -o json␊
// Error: rpc error: code = Unknown desc = path "published.agoricNames.chainConnection.[\\"agoriclocal\\",\\"cosmoshub-4\\"]" contains invalid characters: panic␊
test('chain connection', async t => {
const connection = await queryData(
'published.agoricNames.chainConnection.["agoriclocal","cosmoshub-4"]',
'published.agoricNames.chainConnection.cosmoshub-4_juno-1',
);
console.log(connection);
t.like(connection, {});
t.like(connection, { transferChannel: { portId: 'transfer' } });
});
44 changes: 37 additions & 7 deletions packages/boot/test/bootstrapTests/orchestration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { start as startStakeIca } from '@agoric/orchestration/src/examples/
import type { Instance } from '@agoric/zoe/src/zoeService/utils.js';
import { M, matches } from '@endo/patterns';
import type { TestFn } from 'ava';
import { documentStorageSchema } from '@agoric/internal/src/storage-test-utils.js';
import {
makeWalletFactoryContext,
type WalletFactoryTestContext,
Expand All @@ -27,19 +28,48 @@ test.after.always(t => t.context.shutdown?.());
*/
test.serial('config', async t => {
const {
storage,
readLatest,
runUtils: { EV },
} = t.context;

const agoricNames = await EV.vat('bootstrap').consumeItem('agoricNames');

const cosmosChainInfo = await EV(agoricNames).lookup('chain', 'cosmoshub');
t.like(cosmosChainInfo, {
chainId: 'cosmoshub-4',
stakingTokens: [{ denom: 'uatom' }],
});
const cosmosInfo = readLatest(`published.agoricNames.chain.cosmoshub`);
t.deepEqual(cosmosInfo, cosmosChainInfo);
{
const cosmosChainInfo = await EV(agoricNames).lookup('chain', 'cosmoshub');
t.like(cosmosChainInfo, {
chainId: 'cosmoshub-4',
stakingTokens: [{ denom: 'uatom' }],
});
t.deepEqual(
readLatest(`published.agoricNames.chain.cosmoshub`),
cosmosChainInfo,
);
await documentStorageSchema(t, storage, {
note: 'Chain info for Orchestration',
node: 'agoricNames.chain',
});
}

{
const connection = await EV(agoricNames).lookup(
'chainConnection',
'cosmoshub-4_juno-1',
);

t.like(
readLatest(`published.agoricNames.chainConnection.cosmoshub-4_juno-1`),
{
state: 3,
transferChannel: { portId: 'transfer', state: 3 },
},
);

await documentStorageSchema(t, storage, {
note: 'Chain connections for Orchestration',
node: 'agoricNames.chainConnection',
});
}
});

test.serial('stakeAtom - repl-style', async t => {
Expand Down
399 changes: 399 additions & 0 deletions packages/boot/test/bootstrapTests/snapshots/orchestration.test.ts.md

Large diffs are not rendered by default.

Binary file not shown.
38 changes: 1 addition & 37 deletions packages/governance/tools/storageDoc.js
Original file line number Diff line number Diff line change
@@ -1,37 +1 @@
import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js';

/**
* @param {import('ava').ExecutionContext<unknown>} t
* @param {import('@agoric/internal/src/storage-test-utils.js').MockChainStorageRoot} storage
* @param {({ note: string } | { node: string, owner: string }) &
* ({ pattern: string, replacement: string } | {})
* } opts
*/
export const documentStorageSchema = async (t, storage, opts) => {
// chainStorage publication is unsynchronized
await eventLoopIteration();

const { pattern, replacement } =
'pattern' in opts
? opts
: { pattern: 'mockChainStorageRoot.', replacement: 'published.' };
const illustration = [...storage.keys()].sort().map(
/** @type {(k: string) => [string, unknown]} */
key => [key.replace(pattern, replacement), storage.getBody(key)],
);
const pruned = illustration.filter(
'node' in opts
? ([key, _]) => key.startsWith(`published.${opts.node}`)
: _entry => true,
);

const note =
'note' in opts
? opts.note
: `Under "published", the "${opts.node}" node is delegated to ${opts.owner}.`;
const boilerplate = `
The example below illustrates the schema of the data published there.
See also board marshalling conventions (_to appear_).`;
t.snapshot(pruned, note + boilerplate);
};
export { documentStorageSchema } from '@agoric/internal/src/storage-test-utils.js';
12 changes: 6 additions & 6 deletions packages/inter-protocol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import { makeFollower } from '@agoric/casting';

The canonical keys (under `published`) are as follows. Non-terminal nodes could have data but don't yet. A `0` indicates the index of that child in added order. To get the actual key look it up in parent. High cardinality types get a parent key for enumeration (e.g. `vaults`.)
- `published`
- `vaultFactory` - [snapshot of details](./test/vaultFactory/snapshots/test-vaultFactory.js.md)
- `vaultFactory` - [snapshot of details](./test/vaultFactory/snapshots/vaultFactory.test.js.md)
- `governance`
- `metrics`
- `managers`
Expand All @@ -51,22 +51,22 @@ The canonical keys (under `published`) are as follows. Non-terminal nodes could
- `governance`
- `vaults`
- `vault0`
- `auction` - [snapshot of details](./test/auction/snapshots/test-auctionContract.js.md)
- `auction` - [snapshot of details](./test/auction/snapshots/auctionContract.test.js.md)
- `schedule`
- `governance`
- `book0`
- `reserve` - [snapshot of details](./test/reserve/snapshots/test-reserve.js.md)
- `reserve` - [snapshot of details](./test/reserve/snapshots/reserve.test.js.md)
- `governance`
- `metrics`
- `priceFeed` - [snapshot of details](./test/price/snapshots/test-fluxAggregatorKit.js.md)
- `priceFeed` - [snapshot of details](./test/price/snapshots/fluxAggregatorKit.test.js.md)
- `${inputBrand}-${outputBrand}_price_feed`
- `${inputBrand}-${outputBrand}_price_feed.latestRound`
- `psm` - [snapshot of details](./test/psm/snapshots/test-psm.js.md)
- `psm` - [snapshot of details](./test/psm/snapshots/psm.test.js.md)
- `<minted>`
- `<anchor>`
- `governance`
- `metrics`
- `committees` - [snapshot of details](../governance/test/unitTests/snapshots/test-committee.js.md)
- `committees` - [snapshot of details](../governance/test/unitTests/snapshots/committee.test.js.md)
- `Economic_Committee`
- `latestQuestion`
- `latestOutcome`
Expand Down
2 changes: 1 addition & 1 deletion packages/inter-protocol/test/auction/README-bidding-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ $ inter bid list --from test-acct --all | jq
}
```

See also [test-inter-cli.js.md](https://github.com/Agoric/agoric-sdk/blob/master/packages/agoric-cli/test/snapshots/test-inter-cli.js.md) for exhaustive command options.
See also [test-inter-cli.js.md](../../../agoric-cli/test/snapshots/inter-cli.test.js.md) for exhaustive command options.

## Installation

Expand Down
41 changes: 41 additions & 0 deletions packages/internal/src/storage-test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { unmarshalFromVstorage } from './marshal.js';
import { makeTracer } from './debug.js';
import { isStreamCell, makeChainStorageRoot } from './lib-chainStorage.js';
import { bindAllMethods } from './method-tools.js';
import { eventLoopIteration } from './testing-utils.js';

/**
* @import {Marshaller, StorageEntry, StorageMessage, StorageNode} from './lib-chainStorage.js';
Expand Down Expand Up @@ -254,3 +255,43 @@ export const makeMockChainStorageRoot = () => {
keys: () => [...data.keys()],
});
};

/**
* @param {import('ava').ExecutionContext<unknown>} t
* @param {MockChainStorageRoot | FakeStorageKit} storage
* @param {({ note: string } | { node: string; owner: string }) &
* ({ pattern: string; replacement: string } | {})} opts
*/
export const documentStorageSchema = async (t, storage, opts) => {
// chainStorage publication is unsynchronized
await eventLoopIteration();

const [keys, getBody] =
'keys' in storage
? [storage.keys(), (/** @type {string} */ k) => storage.getBody(k)]
: [storage.data.keys(), (/** @type {string} */ k) => storage.data.get(k)];

const { pattern, replacement } =
'pattern' in opts
? opts
: { pattern: 'mockChainStorageRoot.', replacement: 'published.' };
const illustration = [...keys].sort().map(
/** @type {(k: string) => [string, unknown]} */
key => [key.replace(pattern, replacement), getBody(key)],
);
const pruned = illustration.filter(
'node' in opts
? ([key, _]) => key.startsWith(`published.${opts.node}`)
: _entry => true,
);

const note =
'note' in opts
? opts.note
: `Under "published", the "${opts.node}" node is delegated to ${opts.owner}.`;
const boilerplate = `
The example below illustrates the schema of the data published there.
See also board marshalling conventions (_to appear_).`;
t.snapshot(pruned, note + boilerplate);
};
13 changes: 9 additions & 4 deletions packages/orchestration/scripts/fetch-chain-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const client = new ChainRegistryClient({
// chain info, assets and ibc data will be downloaded dynamically by invoking fetchUrls method
await client.fetchUrls();

const chainInfo = {} as Record<string, CosmosChainInfo>;

function toConnectionEntry(ibcInfo: IBCInfo, name: string) {
// IbcInfo encodes the undirected edge as a tuple of (chain_1, chain_2) in alphabetical order
const fromChain1 = ibcInfo.chain_1.chain_name === name;
Expand Down Expand Up @@ -90,13 +92,12 @@ function toConnectionEntry(ibcInfo: IBCInfo, name: string) {
version: channel.version,
},
} as IBCConnectionInfo;
return [to.chain_name, record];
const destChainId = chainInfo[to.chain_name].chainId;
return [destChainId, record];
}

const chainInfo = {} as Record<string, CosmosChainInfo>;

for (const name of chainNames) {
console.log('processing', name);
console.log('processing info', name);

const chain = client.getChain(name);
chainInfo[name] = {
Expand All @@ -107,6 +108,10 @@ for (const name of chainNames) {
if (name === 'osmosis') {
chainInfo[name].icqEnabled = true;
}
}
// iterate this after chainInfo is filled out
for (const name of chainNames) {
console.log('processing connections', name);

const ibcData = client.getChainIbcData(name);
chainInfo[name].connections = Object.fromEntries(
Expand Down
Loading

0 comments on commit 1d94913

Please sign in to comment.