Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AssetReserve to Upgrade 19 with A3P test coverage #10541

Merged
merged 22 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c267011
test: Check allocations after upgrade
iomekam Nov 19, 2024
c0fd937
Merge branch 'master' into iomekam-ar-upgrade-tests
iomekam Nov 20, 2024
ebbfa73
WIP: push up proposal and attempts at a test
iomekam Dec 6, 2024
3d92f6b
Merge branch 'iomekam-asset-reserve-a3p' into iomekam-ar-upgrade-tests
iomekam Dec 6, 2024
1672768
test(reserve): add a3p tests for testing reserve upgrade
iomekam Dec 11, 2024
09c9747
feat(reserve): add upgrade to upgrade list
iomekam Dec 11, 2024
f39d6f7
test(reserve): renable u19 tests
iomekam Dec 11, 2024
5c38c28
Merge branch 'master' of https://github.com/Agoric/agoric-sdk into io…
iomekam Dec 11, 2024
d6b63b0
test(reserve): update test description
iomekam Dec 11, 2024
59d2615
Merge branch 'master' into iomekam-ar-upgrade-tests
iomekam Dec 11, 2024
1b785b4
test(reserve): remove autogenerated file
iomekam Dec 11, 2024
a9436f2
Merge branch 'iomekam-ar-upgrade-tests' of https://github.com/Agoric/…
iomekam Dec 11, 2024
4bd67a3
fix(reserve): Address PR feedback and change reserveKit adminFacet in…
iomekam Dec 13, 2024
262a901
Merge branch 'master' into iomekam-ar-upgrade-tests
iomekam Dec 13, 2024
391d6bf
fix(reserve): linting
iomekam Dec 16, 2024
f66de07
fix(reserve): add missing collaterel proposal
iomekam Dec 16, 2024
bd7fa60
Merge branch 'iomekam-ar-upgrade-tests' of https://github.com/Agoric/…
iomekam Dec 16, 2024
f391365
fixup! fix(reserve): add missing collaterel proposal
iomekam Dec 16, 2024
b17f601
test(reserve): remove unneeded t.pass()
iomekam Dec 16, 2024
a62afad
Merge branch 'master' of https://github.com/Agoric/agoric-sdk into io…
iomekam Dec 16, 2024
6e125cf
Merge branch 'master' into iomekam-ar-upgrade-tests
mergify[bot] Dec 16, 2024
95f6cf3
Merge branch 'master' into iomekam-ar-upgrade-tests
mergify[bot] Dec 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions a3p-integration/proposals/p:upgrade-19/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ upgradeProvisionPool/
upgradeAgoricNames/
publishTestInfo/
upgrade-mintHolder/
upgradeAssetReserve/
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"consume": {
"contractKits": true,
"zoe": true,
"agoricNames": true,
"reserveKit": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// @ts-nocheck
/* eslint-disable no-undef */

const addCollateral = async powers => {
const {
consume: {
contractKits: contractKitsP,
reserveKit: reserveKitP,
zoe,
agoricNames,
},
} = powers;

const [contractKits, reserveKit, usdLemonsIssuer, usdLemonsBrand] =
await Promise.all([
contractKitsP,
reserveKitP,
E(agoricNames).lookup('issuer', 'USD_LEMONS'),
E(agoricNames).lookup('brand', 'USD_LEMONS'),
]);

console.log('[CONTRACT_KITS]', contractKits);
console.log('[ISSUER]', usdLemonsIssuer);

const { governorCreatorFacet } = reserveKit;

const arPublicFacet = await E(governorCreatorFacet).getPublicFacet();
const arLimitedFacet = await E(governorCreatorFacet).getCreatorFacet();

let usdLemonsMint;
for (const { publicFacet, creatorFacet: mint } of contractKits.values()) {
if (publicFacet === usdLemonsIssuer) {
usdLemonsMint = mint;
console.log('USD_LEMONS found', mint);
break;
}
}

await E(arLimitedFacet).addIssuer(usdLemonsIssuer, 'USD_LEMONS');

console.log('Minting USD_LEMONS');
const amt = harden({ brand: usdLemonsBrand, value: 500000n });
const helloPayment = await E(usdLemonsMint).mintPayment(amt);

console.log('Adding to the reserve...');

const seat = E(zoe).offer(
E(arPublicFacet).makeAddCollateralInvitation(),
harden({
give: { Collateral: amt },
}),
harden({ Collateral: helloPayment }),
);

console.log(await E(seat).getOfferResult());
console.log('Done.');
};

addCollateral;
92 changes: 92 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/assetReserve.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* eslint-env node */
/**
* @file The goal of this file is to make sure v36-reserve upgraded.
*
* The test scenario is as follows;
* 1. Add asset USD_LEMONS
* 2. Add collateral to the reserve
* 3. Upgrade reserve
* 4. Ensure that the collateral is still in the reserve
*/

import '@endo/init';
import test from 'ava';
import {
evalBundles,
agd as agdAmbient,
agoric,
getDetailsMatchingVats,
} from '@agoric/synthetic-chain';
import {
makeVstorageKit,
waitUntilContractDeployed,
} from '@agoric/client-utils';

const ADD_PSM_DIR = 'addUsdLemons';
const UPGRADE_AR_DIR = 'upgradeAssetReserve';
const ADD_COLLATERAL = 'addCollateral';

const ambientAuthority = {
query: agdAmbient.query,
follow: agoric.follow,
setTimeout,
log: console.log,
};

/**
* @typedef {import('@agoric/ertp').NatAmount} NatAmount
* @typedef {{
* allocations: { Fee: NatAmount, USD_LEMONS: NatAmount },
* }} ReserveAllocations
*/

test.before(async t => {
const vstorageKit = await makeVstorageKit(
{ fetch },
{ rpcAddrs: ['http://localhost:26657'], chainName: 'agoriclocal' },
);

t.context = {
vstorageKit,
};
});

test.serial('add collatoral to reserve', async t => {
// @ts-expect-error casting
const { vstorageKit } = t.context;

// Introduce USD_LEMONS
await evalBundles(ADD_PSM_DIR);
await waitUntilContractDeployed('psm-IST-USD_LEMONS', ambientAuthority, {
errorMessage: 'psm-IST-USD_LEMONS instance not observed.',
});

await evalBundles(ADD_COLLATERAL);

const metrics = /** @type {ReserveAllocations} */ (
await vstorageKit.readLatestHead('published.reserve.metrics')
);

t.truthy(Object.keys(metrics.allocations).includes('USD_LEMONS'));
t.is(metrics.allocations.USD_LEMONS.value, 500000n);
});

test.serial('upgrade', async t => {
// @ts-expect-error casting
const { vstorageKit } = t.context;

await evalBundles(UPGRADE_AR_DIR);

const vatDetailsAfter = await getDetailsMatchingVats('reserve');
const { incarnation } = vatDetailsAfter.find(vat => vat.vatID === 'v36'); // assetReserve is v36

t.log(vatDetailsAfter);
t.is(incarnation, 1, 'incorrect incarnation');

const metrics = /** @type {ReserveAllocations} */ (
await vstorageKit.readLatestHead('published.reserve.metrics')
);

t.truthy(Object.keys(metrics.allocations).includes('USD_LEMONS'));
t.is(metrics.allocations.USD_LEMONS.value, 500000n);
});
1 change: 1 addition & 0 deletions a3p-integration/proposals/p:upgrade-19/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"testing/replace-feeDistributor-short.js replaceFeeDistributor",
"testing/add-USD-LEMONS.js addUsdLemons",
"vats/upgrade-provisionPool.js upgradeProvisionPool",
"vats/upgrade-asset-reserve.js upgradeAssetReserve",
"vats/upgrade-paRegistry.js",
"vats/upgrade-board.js",
"testing/test-upgraded-board.js testUpgradedBoard",
Expand Down
3 changes: 3 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ yarn ava replaceFeeDistributor.test.js
yarn ava upgradedBoard.test.js
yarn ava mintHolder.test.js
yarn ava provisionPool.test.js

yarn ava agoricNames.test.js

yarn ava assetReserve.test.js
3 changes: 3 additions & 0 deletions golang/cosmos/app/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ func unreleasedUpgradeHandler(app *GaiaApp, targetUpgrade string) func(sdk.Conte
// vm.CoreProposalStepForModules(
// "@agoric/builders/scripts/vats/upgrade-agoricNames.js",
// ),
// vm.CoreProposalStepForModules(
// "@agoric/builders/scripts/vats/upgrade-asset-reserve.js",
// ),
// )
}

Expand Down
21 changes: 21 additions & 0 deletions packages/builders/scripts/vats/upgrade-asset-reserve.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { makeHelpers } from '@agoric/deploy-script-support';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */
export const defaultProposalBuilder = async ({ publishRef, install }) =>
harden({
sourceSpec: '@agoric/vats/src/proposals/upgrade-asset-reserve-proposal.js',
getManifestCall: [
'getManifestForUpgradingAssetReserve',
{
assetReserveRef: publishRef(
install('@agoric/inter-protocol/src/reserve/assetReserve.js'),
),
},
],
});

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').DeployScriptFunction} */
export default async (homeP, endowments) => {
const { writeCoreProposal } = await makeHelpers(homeP, endowments);
await writeCoreProposal('upgrade-asset-reserve', defaultProposalBuilder);
};
5 changes: 3 additions & 2 deletions packages/inter-protocol/src/proposals/econ-behaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,10 @@ export const setupReserve = async ({
'reserve.governor',
);

const [creatorFacet, publicFacet, instance] = await Promise.all([
const [creatorFacet, publicFacet, adminFacet, instance] = await Promise.all([
E(g.creatorFacet).getCreatorFacet(),
E(g.creatorFacet).getPublicFacet(),
E(g.creatorFacet).getAdminFacet(),
E(g.publicFacet).getGovernedContract(),
]);

Expand All @@ -169,7 +170,7 @@ export const setupReserve = async ({
instance,
publicFacet,
creatorFacet,
adminFacet: g.adminFacet,
adminFacet,

governor: g.instance,
governorCreatorFacet: g.creatorFacet,
Expand Down
21 changes: 6 additions & 15 deletions packages/inter-protocol/src/reserve/assetReserve.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,13 @@ export const start = async (zcf, privateArgs, baggage) => {
privateArgs.marshaller,
);

/** @type {() => Promise<ZCFMint<'nat'>>} */
const takeFeeMint = async () => {
if (baggage.has('feeMint')) {
return baggage.get('feeMint');
}

const feeMintTemp = await zcf.registerFeeMint(
'Fee',
privateArgs.feeMintAccess,
);
baggage.init('feeMint', feeMintTemp);
return feeMintTemp;
};
trace('awaiting takeFeeMint');
const feeMint = await takeFeeMint();
const storageNode = await privateArgs.storageNode;

trace('awaiting feeMint');
const { feeMint } = await provideAll(baggage, {
feeMint: () => zcf.registerFeeMint('Fee', privateArgs.feeMintAccess),
});

Comment on lines +63 to +66
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming the feeMint wasn't already in the baggage, which is why takeFeeMint() was failing, how did provideAll solved the "no contact with other vats during the first crank of the new incarnation"? Does provideAll somehow delay the execution of zcf.registerFeeMint to another crank?

cc @Chris-Hibbert

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feeMint was already in baggage. It was failing because we were upgrading the governor contract instead of the reserve contract, which I assume has a different baggage attached to it. provideAll just abstracts the logic of creating the item in baggage on the first incarnation and then checking the value on future upgrades.

const makeAssetReserveKit = await prepareAssetReserveKit(baggage, {
feeMint,
makeRecorderKit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ export const buildRootObject = async () => {

metricsRecord = await E(metrics).getUpdateSince();

// verify allocations
const allocations = await E(arLimitedFacet).getAllocations();
assert.equal(allocations.Moola.value, 100_000n);
assert.equal(allocations.Moola.brand, moola.brand);

// same as last
assert.equal(metricsRecord.updateCount, 2n);

Expand Down
93 changes: 93 additions & 0 deletions packages/vats/src/proposals/upgrade-asset-reserve-proposal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { E } from '@endo/far';
import { deeplyFulfilled } from '@endo/marshal';
import { makeTracer } from '@agoric/internal';

const tracer = makeTracer('UpgradeAssetReserve');

/**
* @param {BootstrapPowers & {
* consume: {
* economicCommitteeCreatorFacet: any;
* reserveKit: any;
* };
* produce: {
* reserveKit: any;
* };
* }} powers
* @param {object} options
* @param {{ assetReserveRef: VatSourceRef }} options.options
*/
export const upgradeAssetReserve = async (
{
consume: {
economicCommitteeCreatorFacet: electorateCreatorFacet,
reserveKit: reserveKitP,
instancePrivateArgs: instancePrivateArgsP,
},
produce: { reserveKit: reserveKitWriter },
},
options,
) => {
const { assetReserveRef } = options.options;

assert(assetReserveRef.bundleID);
tracer(`ASSET RESERVE BUNDLE ID: `, assetReserveRef);

const [reserveKit, instancePrivateArgs] = await Promise.all([
reserveKitP,
instancePrivateArgsP,
]);
const { governorCreatorFacet, instance } = reserveKit;

const [originalPrivateArgs, poserInvitation] = await Promise.all([
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore Local tsc sees this as an error but typedoc does not
deeplyFulfilled(instancePrivateArgs.get(instance)),
E(electorateCreatorFacet).getPoserInvitation(),
]);

const newPrivateArgs = harden({
...originalPrivateArgs,
initialPoserInvitation: poserInvitation,
});

const adminFacet = await E(governorCreatorFacet).getAdminFacet();

// We need to reset the kit and produce a new adminFacet because the
// original contract is producing an admin facet that is for the
// governor, not the reserve.
reserveKitWriter.reset();
reserveKitWriter.resolve(
harden({
...reserveKit,
adminFacet,
}),
);
Comment on lines +59 to +65
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as you're doing this, might as well clean up the original, (we want those proposals to be usable to start a new chain, or to copy, even if we won't run them again on mainNet) and add a comment here as to why this fix is necessary.


const upgradeResult = await E(adminFacet).upgradeContract(
assetReserveRef.bundleID,
newPrivateArgs,
);

tracer('AssetReserve upgraded: ', upgradeResult);
tracer('Done.');
};

export const getManifestForUpgradingAssetReserve = (
_powers,
{ assetReserveRef },
) => ({
manifest: {
[upgradeAssetReserve.name]: {
consume: {
economicCommitteeCreatorFacet: true,
instancePrivateArgs: true,
reserveKit: true,
},
produce: {
reserveKit: true,
},
},
},
options: { assetReserveRef },
});
Loading