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

6701 EC removeOracles #6977

Merged
merged 5 commits into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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();
Copy link
Member

Choose a reason for hiding this comment

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

I wonder why disable rather than revoke. Can it be enabled again?

(thanks for adding the JS standard revoke() thing to https://github.com/dckc/awesome-ocap/wiki/CareTaker )

Copy link
Member Author

Choose a reason for hiding this comment

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

that was the idea. right now there's no enable() method but the state is a boolean so it could be toggled.

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';
Copy link
Member Author

Choose a reason for hiding this comment

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

this is really a rename 1023f04

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', {
turadg marked this conversation as resolved.
Show resolved Hide resolved
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