Skip to content

Commit

Permalink
Merge pull request #6977 from Agoric/6701-ec-removeOracles
Browse files Browse the repository at this point in the history
6701 EC removeOracles
  • Loading branch information
mergify[bot] authored Feb 13, 2023
2 parents af4d93b + 9b6e2cd commit 943b3a4
Show file tree
Hide file tree
Showing 10 changed files with 571 additions and 488 deletions.
25 changes: 13 additions & 12 deletions packages/inter-protocol/src/price/fluxAggregator.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from '@agoric/zoe/src/contractSupport/index.js';
import { E } from '@endo/eventual-send';
import { Far } from '@endo/marshal';
import { makeOracleAdmin } from './priceOracleAdmin.js';
import { makeOracleAdminKit } from './priceOracleKit.js';
import { makeRoundsManagerKit } from './roundsManager.js';

const trace = makeTracer('FlxAgg', false);
Expand Down Expand Up @@ -132,7 +132,7 @@ export const provideFluxAggregator = (

const memoizedPath = makeStorageNodePathProvider(baggage);

/** @type {MapStore<string, *>} */
/** @type {MapStore<string, import('./priceOracleKit.js').OracleKit>} */
const oracles = makeScalarBigMapStore('oracles', {
durable: true,
});
Expand Down Expand Up @@ -211,15 +211,15 @@ export const provideFluxAggregator = (
* @param {ZCFSeat} seat
*/
const offerHandler = async seat => {
const admin = await creatorFacet.initOracle(oracleId);
const { oracle } = await creatorFacet.initOracle(oracleId);
const invitationMakers = Far('invitation makers', {
/** @param {import('./roundsManager.js').PriceRound} result */
PushPrice(result) {
return zcf.makeInvitation(
/** @param {ZCFSeat} cSeat */
async cSeat => {
cSeat.exit();
await admin.pushPrice(result);
await oracle.pushPrice(result);
},
'PushPrice',
);
Expand All @@ -228,17 +228,18 @@ export const provideFluxAggregator = (
seat.exit();

return harden({
admin,

invitationMakers,
oracle,
});
};

return zcf.makeInvitation(offerHandler, INVITATION_MAKERS_DESC);
},
/** @param {string} oracleId */
deleteOracle: async oracleId => {
// FIXME how to GC and remove its powers?
removeOracle: async oracleId => {
trace('deleteOracle', oracleId);
const kit = oracles.get(oracleId);
kit.admin.disable();
oracles.delete(oracleId);
},

Expand All @@ -251,7 +252,7 @@ export const provideFluxAggregator = (
trace('initOracle', oracleId);
assert.typeof(oracleId, 'string');

const oracleAdmin = makeOracleAdmin(
const oracleKit = makeOracleAdminKit(
harden({
minSubmissionValue,
maxSubmissionValue,
Expand All @@ -260,9 +261,9 @@ export const provideFluxAggregator = (
timer: timerPresence,
}),
);
oracles.init(oracleId, oracleAdmin);
oracles.init(oracleId, oracleKit);

return oracleAdmin;
return oracleKit;
},

/**
Expand All @@ -275,7 +276,7 @@ export const provideFluxAggregator = (
*/
async oracleRoundState(oracleId, queriedRoundId) {
const blockTimestamp = await E(timerPresence).getCurrentTimestamp();
const status = await E(oracles.get(oracleId)).getStatus();
const status = await E(oracles.get(oracleId).oracle).getStatus();

const oracleCount = oracles.getSize();

Expand Down
24 changes: 23 additions & 1 deletion packages/inter-protocol/src/price/fluxAggregatorContract.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,12 @@ export const start = async (zcf, privateArgs, baggage) => {
);

/**
* Initialize a new oracle and send an invitation to administer it.
* Initialize a new oracle and send an invitation to control it.
*
* @param {string} addr
*/
const addOracle = async addr => {
trace('addOracle', addr);
const invitation = await E(fa.creatorFacet).makeOracleInvitation(addr);
// XXX imported from 'proposals' path
await reserveThenDeposit(
Expand All @@ -97,6 +98,17 @@ export const start = async (zcf, privateArgs, baggage) => {
return `added ${addr}`;
};

/**
* Remove an oracle from aggregation and disable its facet.
*
* @param {string} oracleId
*/
const removeOracle = async oracleId => {
trace('removeOracle', oracleId);
await E(fa.creatorFacet).removeOracle(oracleId);
return `removed ${oracleId}`;
};

const governedApis = {
/**
* Add the specified oracles. May partially fail, such that some oracles are added and others aren't.
Expand All @@ -107,6 +119,16 @@ export const start = async (zcf, privateArgs, baggage) => {
addOracles: oracleIds => {
return Promise.allSettled(oracleIds.map(addOracle));
},
/**
* Remove the specified oracles. May partially fail, such that some oracles are removed and others aren't.
* If the oracle was never part of the set that's a PromiseRejectedResult
*
* @param {string[]} oracleIds
* @returns {Promise<Array<PromiseSettledResult<string>>>}
*/
removeOracles: oracleIds => {
return Promise.allSettled(oracleIds.map(removeOracle));
},
};

const governorFacet = makeGovernorFacet(fa.creatorFacet, governedApis);
Expand Down
101 changes: 0 additions & 101 deletions packages/inter-protocol/src/price/priceOracleAdmin.js

This file was deleted.

124 changes: 124 additions & 0 deletions packages/inter-protocol/src/price/priceOracleKit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { Fail } from '@agoric/assert';
import { makeTracer } from '@agoric/internal';
import { defineDurableExoClassKit, M, makeKindHandle } from '@agoric/vat-data';

const trace = makeTracer('OrKit', false);

export const INVITATION_MAKERS_DESC = 'oracle invitation';

/**
* @typedef {{
* oracleId: string,
* roundPowers: { handlePush: (status: OracleStatus, result: import('./roundsManager.js').PriceRound) => Promise<OracleStatus> }
* }} HeldParams
*/

/**
* @typedef {{ roundId: number | undefined, unitPrice: NatValue }} PriceDatum
*/

/**
* @typedef {object} OracleStatus
* @property {boolean} [disabled]
* @property {bigint} lastReportedRound
* @property {bigint} lastStartedRound
* @property {bigint} latestSubmission
* @property {string} oracleId
*/
/**
* @typedef {Readonly<HeldParams & {
* }>} ImmutableState
*
* @typedef {OracleStatus & {
* }} MutableState
*/
/** @typedef {ImmutableState & MutableState} State */

const oracleKitKind = makeKindHandle('OracleKit');

/**
* @param {HeldParams} heldParams
* @returns {State}
*/
const initState = ({ oracleId, roundPowers }) => {
return {
oracleId,
roundPowers,
disabled: false,
lastReportedRound: 0n,
lastStartedRound: 0n,
latestSubmission: 0n,
};
};

const AdminI = M.interface('OracleKitAdmin', {
disable: M.call().returns(),
});

const OracleI = M.interface('Oracle', {
pushPrice: M.call({ roundId: M.any(), unitPrice: M.bigint() }).returns(
M.promise(),
),
getStatus: M.call().returns(M.record()),
});

export const makeOracleAdminKit = defineDurableExoClassKit(
oracleKitKind,
{ admin: AdminI, oracle: OracleI },
initState,
{
admin: {
disable() {
trace(`oracle ${this.state.oracleId} disabled`);
this.state.disabled = true;
},
},
oracle: {
/**
* push a unitPrice result from this oracle
*
* @param {PriceDatum} datum
*/
async pushPrice({
roundId: roundIdRaw = undefined,
unitPrice: valueRaw,
}) {
const { state } = this;
!state.disabled || Fail`pushPrice for disabled oracle`;
const { roundPowers } = state;
const result = await roundPowers.handlePush(
{
oracleId: state.oracleId,
lastReportedRound: state.lastReportedRound,
lastStartedRound: state.lastStartedRound,
latestSubmission: state.latestSubmission,
},
{
roundId: roundIdRaw,
unitPrice: valueRaw,
},
);

state.lastReportedRound = result.lastReportedRound;
state.lastStartedRound = result.lastStartedRound;
state.latestSubmission = result.latestSubmission;
},
/**
*
* @returns {OracleStatus}
*/
getStatus() {
const { state } = this;
return {
oracleId: state.oracleId,
disabled: state.disabled,
lastReportedRound: state.lastReportedRound,
lastStartedRound: state.lastStartedRound,
latestSubmission: state.latestSubmission,
};
},
},
},
);

/** @typedef {ReturnType<typeof makeOracleAdminKit>} OracleKit */
2 changes: 1 addition & 1 deletion packages/inter-protocol/src/price/roundsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { UnguardedHelperI } from '../typeGuards.js';

const { add, subtract, multiply, floorDivide, ceilDivide, isGTE } = natSafeMath;

/** @typedef {import('./priceOracleAdmin.js').OracleStatus} OracleStatus */
/** @typedef {import('./priceOracleKit.js').OracleStatus} OracleStatus */
/**
* @typedef {import('@agoric/time/src/types').Timestamp} Timestamp
* @typedef {import('@agoric/time/src/types').TimerService} TimerService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ export const createPriceFeed = async (

trace('awaiting startInstance');
// Create the price feed.
/** @type {{ creatorFacet: import('@agoric/governance/src/contractGovernor.js').GovernedContractFnFacetAccess<import('@agoric/inter-protocol/src/price/fluxAggregator.contract.js').start>, publicFacet: GovernorPublic, instance: Instance, adminFacet: AdminFacet }} */
const aggregatorGovernor = await E(zoe).startInstance(
contractGovernor,
undefined,
Expand Down
Loading

0 comments on commit 943b3a4

Please sign in to comment.