Skip to content

Commit

Permalink
support changes to governed APIs (#10822)
Browse files Browse the repository at this point in the history
closes: #9990

## Description

When a contract is upgraded, we'll read the governed APIs afresh.

### Security Considerations

Nothing special. The point of governed APIs is that contracts can make access to calling specific APIs legible in the sense used by governance.

### Scaling Considerations

Not an issue.

### Documentation Considerations

If we had detailed documentation on governance, this would be worth adding to the docs.

### Testing Considerations

Added a bootstrap test showing that a contract can be upgraded and the new APIs will be available after upgrade.

### Upgrade Considerations

AssetReserve, fluxAggregator, and VaultFactory use `apiGovernance` and might need this support if any governed APIs were added.
  • Loading branch information
mergify[bot] authored Jan 22, 2025
2 parents cb12196 + ffe2dd6 commit f5bf658
Show file tree
Hide file tree
Showing 10 changed files with 534 additions and 21 deletions.
1 change: 1 addition & 0 deletions packages/boot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@agoric/cosmic-swingset": "^0.41.3",
"@agoric/ertp": "^0.16.2",
"@agoric/fast-usdc": "0.1.0",
"@agoric/governance": "^0.10.3",
"@agoric/inter-protocol": "^0.16.1",
"@agoric/internal": "^0.3.2",
"@agoric/kmarshal": "^0.1.0",
Expand Down
85 changes: 85 additions & 0 deletions packages/boot/test/bootstrapTests/governedContract.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import {
CONTRACT_ELECTORATE,
ParamTypes,
handleParamGovernance,
} from '@agoric/governance';
import { prepareExoClassKit, provide } from '@agoric/vat-data';

/**
* @import {GovernanceTerms} from '@agoric/governance/src/types.js';
* @import {Baggage} from '@agoric/vat-data';
*/

const MALLEABLE_NUMBER = 'MalleableNumber';

const makeTerms = (number, invitationAmount) => {
return harden({
governedParams: {
[MALLEABLE_NUMBER]: { type: ParamTypes.NAT, value: number },
[CONTRACT_ELECTORATE]: {
type: ParamTypes.INVITATION,
value: invitationAmount,
},
},
});
};

/**
*
* @param {ZCF<
* GovernanceTerms<{
* MalleableNumber: 'nat',
* }>>} zcf
* @param {{initialPoserInvitation: Invitation}} privateArgs
* @param {Baggage} baggage
*/
const start = async (zcf, privateArgs, baggage) => {
const { makeDurableGovernorFacet, params } = await handleParamGovernance(
zcf,
privateArgs.initialPoserInvitation,
{
[MALLEABLE_NUMBER]: ParamTypes.NAT,
},
);

const makeGoverned = prepareExoClassKit(
baggage,
'governed Public',
undefined,
() =>
harden({
governanceAPICalled: 0,
}),
{
public: {
getNum() {
return params.getMalleableNumber();
},
getApiCalled() {
const { governanceAPICalled } = this.state;
return governanceAPICalled;
},
},
creator: {},
governed: {
add1() {
const { state } = this;
state.governanceAPICalled += 1;
},
},
},
);
const facets = provide(baggage, 'theContract', () => makeGoverned());

const { governorFacet } = makeDurableGovernorFacet(baggage, facets.creator, {
add1: () => facets.governed.add1(),
});

return { publicFacet: facets.public, creatorFacet: governorFacet };
};

harden(start);
harden(MALLEABLE_NUMBER);
harden(makeTerms);

export { start, MALLEABLE_NUMBER, makeTerms };
90 changes: 90 additions & 0 deletions packages/boot/test/bootstrapTests/governedContract2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {
CONTRACT_ELECTORATE,
ParamTypes,
handleParamGovernance,
} from '@agoric/governance';
import { prepareExoClassKit, provide } from '@agoric/vat-data';

/**
* @import {GovernanceTerms} from '@agoric/governance/src/types.js';
* @import {Baggage} from '@agoric/vat-data';
*/

const MALLEABLE_NUMBER = 'MalleableNumber';

const makeTerms = (number, invitationAmount) => {
return harden({
governedParams: {
[MALLEABLE_NUMBER]: { type: ParamTypes.NAT, value: number },
[CONTRACT_ELECTORATE]: {
type: ParamTypes.INVITATION,
value: invitationAmount,
},
},
});
};

/**
*
* @param {ZCF<
* GovernanceTerms<{
* MalleableNumber: 'nat',
* }>>} zcf
* @param {{initialPoserInvitation: Invitation}} privateArgs
* @param {Baggage} baggage
*/
const start = async (zcf, privateArgs, baggage) => {
const { makeDurableGovernorFacet, params } = await handleParamGovernance(
zcf,
privateArgs.initialPoserInvitation,
{
[MALLEABLE_NUMBER]: ParamTypes.NAT,
},
);

const makeGoverned = prepareExoClassKit(
baggage,
'governed Public',
undefined,
() =>
harden({
governanceAPICalled: 0,
}),
{
public: {
getNum() {
return params.getMalleableNumber();
},
getApiCalled() {
const { governanceAPICalled } = this.state;
return governanceAPICalled;
},
},
creator: {},
governed: {
add1() {
const { state } = this;
state.governanceAPICalled += 1;
},
add2() {
const { state } = this;
state.governanceAPICalled += 2;
},
},
},
);
const facets = provide(baggage, 'theContract', () => makeGoverned());

const { governorFacet } = makeDurableGovernorFacet(baggage, facets.creator, {
add1: () => facets.governed.add1(),
add2: () => facets.governed.add2(),
});

return { publicFacet: facets.public, creatorFacet: governorFacet };
};

harden(start);
harden(MALLEABLE_NUMBER);
harden(makeTerms);

export { start, MALLEABLE_NUMBER, makeTerms };
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* We change a parameter so that provideParamGovernance() is called once, and
* paramGoverance has been set. Then upgrade vaultFactory, so any ephemeral
* objects from the contract held by the governor are gone, then try to change
* param again, to show that the bug is fixedd.
* param again, to show that the bug is fixed.
*/
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';

Expand Down
Loading

0 comments on commit f5bf658

Please sign in to comment.