Skip to content

Commit

Permalink
fix: write-chain-info after u17 (#10110)
Browse files Browse the repository at this point in the history
_incidental_

## Description
We don't have a good design yet for the schema of Orchestration chain info in agoricNames,
- #10109

It's not necessary for upgrade-17 so save it for another proposal.

### Security Considerations
none

### Scaling Considerations
none

### Documentation Considerations
SDK still registers the info so the development experience doesn't differ.

### Testing Considerations
Shouldn't break any existing tests.

### Upgrade Considerations
Not yet deployed. Should be part of u17-rc1.
  • Loading branch information
mergify[bot] authored and gibson042 committed Sep 19, 2024
2 parents a61cdab + a25d3c6 commit ed860d5
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 93 deletions.
5 changes: 5 additions & 0 deletions packages/boot/test/bootstrapTests/vat-orchestration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ test.before(async t => {
await evalProposal(
buildProposal('@agoric/builders/scripts/vats/init-orchestration.js'),
);
await evalProposal(
buildProposal(
'@agoric/builders/scripts/orchestration/write-chain-info.js',
),
);
const vatStore = await EV.vat('bootstrap').consumeItem('vatStore');
t.true(await EV(vatStore).has('ibc'), 'ibc');
t.true(await EV(vatStore).has('network'), 'network');
Expand Down
13 changes: 13 additions & 0 deletions packages/builders/scripts/orchestration/write-chain-info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { makeHelpers } from '@agoric/deploy-script-support';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */
export const defaultProposalBuilder = async () =>
harden({
sourceSpec: '@agoric/orchestration/src/proposals/init-chain-info.js',
getManifestCall: ['getManifestForChainInfo'],
});

export default async (homeP, endowments) => {
const { writeCoreEval } = await makeHelpers(homeP, endowments);
await writeCoreEval('gov-orchestration', defaultProposalBuilder);
};
98 changes: 98 additions & 0 deletions packages/orchestration/src/proposals/init-chain-info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { Fail } from '@endo/errors';
import { E, Far } from '@endo/far';
import { makeMarshal } from '@endo/marshal';
import { makeTracer } from '@agoric/internal';
import { registerKnownChains } from '../chain-info.js';
import { CHAIN_KEY, CONNECTIONS_KEY } from '../exos/chain-hub.js';

const trace = makeTracer('InitChainInfo', true);

/**
* Similar to publishAgoricNamesToChainStorage but publishes a node per chain
* instead of one list of entries
*/

/**
* @param {ERef<import('@agoric/vats').NameHubKit['nameAdmin']>} agoricNamesAdmin
* @param {ERef<StorageNode | null>} chainStorageP
*/
const publishChainInfoToChainStorage = async (
agoricNamesAdmin,
chainStorageP,
) => {
const chainStorage = await chainStorageP;
if (!chainStorage) {
console.warn('no chain storage, not registering chain info');
return;
}

const agoricNamesNode = await E(chainStorage).makeChildNode('agoricNames');

/**
* @param {string} subpath
*/
const echoNameUpdates = async subpath => {
const chainNamesNode = E(agoricNamesNode).makeChildNode(subpath);
const { nameAdmin } = await E(agoricNamesAdmin).provideChild(subpath);

/**
* Previous entries, to prevent redundant updates
*
* @type {Record<string, string>} chainName => stringified chainInfo
*/
const prev = {};

// XXX cannot be changed until we upgrade vat-agoricNames to allow it
await E(nameAdmin).onUpdate(
// XXX will live on the heap in the bootstrap vat. When we upgrade or kill
// that this handler will sever and vat-agoricNames will need to be upgraded
// to allow changing the handler, or to use pubsub mechanics instead.
Far('chain info writer', {
write(entries) {
// chainInfo has no cap data but we need to marshal bigints
const marshalData = makeMarshal(_val => Fail`data only`);
for (const [chainName, info] of entries) {
const value = JSON.stringify(marshalData.toCapData(info));
if (prev[chainName] === value) {
continue;
}
const chainNode = E(chainNamesNode).makeChildNode(chainName);
prev[chainName] = value;
void E(chainNode)
.setValue(value)
.catch(() => delete prev[chainName]);
}
},
}),
);
};
await echoNameUpdates(CHAIN_KEY);
await echoNameUpdates(CONNECTIONS_KEY);
};

/**
* @param {BootstrapPowers} powers
*/
export const initChainInfo = async ({
consume: { agoricNamesAdmin, chainStorage: chainStorageP },
}) => {
trace('init-chainInfo');

// First set up callback to write updates to vstorage
await publishChainInfoToChainStorage(agoricNamesAdmin, chainStorageP);

// Now register the names
await registerKnownChains(agoricNamesAdmin, trace);
};
harden(initChainInfo);

export const getManifestForChainInfo = () => ({
manifest: {
[initChainInfo.name]: {
consume: {
agoricNamesAdmin: true,
chainStorage: true,
},
},
},
});
98 changes: 6 additions & 92 deletions packages/orchestration/src/proposals/orchestration-proposal.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { Fail } from '@endo/errors';
import { E, Far } from '@endo/far';
import { makeMarshal } from '@endo/marshal';
import { makeTracer } from '@agoric/internal';
import { registerKnownChains } from '../chain-info.js';
import { CHAIN_KEY, CONNECTIONS_KEY } from '../exos/chain-hub.js';
import { E } from '@endo/far';

const trace = makeTracer('CoreEvalOrchestration', true);

Expand All @@ -27,14 +23,16 @@ export const setupOrchestrationVat = async (
consume: { loadCriticalVat, portAllocator: portAllocatorP },
produce: { orchestrationVat, ...produce },
},
options,
{ options },
) => {
const { orchestrationRef } = options.options;
trace('setupOrchestrationVat', options);
const { orchestrationRef } = options;
const vats = {
orchestration: E(loadCriticalVat)('orchestration', orchestrationRef),
};
// don't proceed if loadCriticalVat fails
await Promise.all(Object.values(vats));
trace('setupOrchestrationVat got vats');

orchestrationVat.reset();
orchestrationVat.resolve(vats.orchestration);
Expand All @@ -49,87 +47,9 @@ export const setupOrchestrationVat = async (

produce.cosmosInterchainService.reset();
produce.cosmosInterchainService.resolve(cosmosInterchainService);
trace('setupOrchestrationVat complete');
};

/**
* Similar to publishAgoricNamesToChainStorage but publishes a node per chain
* instead of one list of entries
*/

/**
* @param {ERef<import('@agoric/vats').NameHubKit['nameAdmin']>} agoricNamesAdmin
* @param {ERef<StorageNode | null>} chainStorageP
*/
const publishChainInfoToChainStorage = async (
agoricNamesAdmin,
chainStorageP,
) => {
const chainStorage = await chainStorageP;
if (!chainStorage) {
console.warn('no chain storage, not registering chain info');
return;
}

const agoricNamesNode = await E(chainStorage).makeChildNode('agoricNames');

/**
* @param {string} subpath
*/
const echoNameUpdates = async subpath => {
const chainNamesNode = E(agoricNamesNode).makeChildNode(subpath);
const { nameAdmin } = await E(agoricNamesAdmin).provideChild(subpath);

/**
* Previous entries, to prevent redundant updates
*
* @type {Record<string, string>} chainName => stringified chainInfo
*/
const prev = {};

// XXX cannot be changed until we upgrade vat-agoricNames to allow it
await E(nameAdmin).onUpdate(
// XXX will live on the heap in the bootstrap vat. When we upgrade or kill
// that this handler will sever and vat-agoricNames will need to be upgraded
// to allow changing the handler, or to use pubsub mechanics instead.
Far('chain info writer', {
write(entries) {
// chainInfo has no cap data but we need to marshal bigints
const marshalData = makeMarshal(_val => Fail`data only`);
for (const [chainName, info] of entries) {
const value = JSON.stringify(marshalData.toCapData(info));
if (prev[chainName] === value) {
continue;
}
const chainNode = E(chainNamesNode).makeChildNode(chainName);
prev[chainName] = value;
void E(chainNode)
.setValue(value)
.catch(() => delete prev[chainName]);
}
},
}),
);
};
await echoNameUpdates(CHAIN_KEY);
await echoNameUpdates(CONNECTIONS_KEY);
};

/**
* @param {BootstrapPowers} powers
*/
export const initChainInfo = async ({
consume: { agoricNamesAdmin, chainStorage: chainStorageP },
}) => {
trace('init-chainInfo');

// First set up callback to write updates to vstorage
await publishChainInfoToChainStorage(agoricNamesAdmin, chainStorageP);

// Now register the names
await registerKnownChains(agoricNamesAdmin, trace);
};
harden(initChainInfo);

export const getManifestForOrchestration = (_powers, { orchestrationRef }) => ({
manifest: {
[setupOrchestrationVat.name]: {
Expand All @@ -142,12 +62,6 @@ export const getManifestForOrchestration = (_powers, { orchestrationRef }) => ({
orchestrationVat: 'orchestrationVat',
},
},
[initChainInfo.name]: {
consume: {
agoricNamesAdmin: true,
chainStorage: true,
},
},
},
options: {
orchestrationRef,
Expand Down
3 changes: 2 additions & 1 deletion packages/vm-config/decentral-devnet-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"@agoric/builders/scripts/vats/init-transfer.js"
],
[
"@agoric/builders/scripts/vats/init-orchestration.js"
"@agoric/builders/scripts/vats/init-orchestration.js",
"@agoric/builders/scripts/orchestration/write-chain-info.js"
],
[
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"@agoric/builders/scripts/vats/init-localchain.js",
"@agoric/builders/scripts/vats/init-transfer.js",
"@agoric/builders/scripts/vats/init-orchestration.js",
"@agoric/builders/scripts/orchestration/write-chain-info.js",
{
"module": "@agoric/builders/scripts/inter-protocol/init-core.js",
"entrypoint": "defaultProposalBuilder",
Expand Down

0 comments on commit ed860d5

Please sign in to comment.