-
Notifications
You must be signed in to change notification settings - Fork 207
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
transaction oracle invitations (#10478)
refs: #10457 ## Description Adds access privileges for the transaction feed oracles. Accounts can be invited to be an oracle. The offer result is a kit that contains direct powers and an `invitationMakers` property for use through the smart-wallet. Includes tests of executing invitations and disabling oracles. This PR doesn't close the issue because there is still the matter of combining oracle results. I plan to have more thorough tests in or after that PR. ### Security Considerations provides an invitation to be an oracle to the transaction feed. These will eventually be tradable but aren't presently. ### Scaling Considerations This hacks the semantics of continuing offers a bit by performing the request in the invitation making function, instead of in the course of the offer. It adds a `defineNoopInvitation` helper to explain this. It's not ideal but the pragmatic path for now ([decision record with rationale](https://alpha.decidedly.co/d/a8d1bfa1-f6d2-4b24-b636-d360b3227289)). ### Documentation Considerations Adds a README with the basic sequence of how the oracles work with the contract ### Testing Considerations More tests coming in other PRs. Some scheduled issues are specifically about testing. ### Upgrade Considerations Not yet live but everything here is meant to be upgradable.
- Loading branch information
Showing
9 changed files
with
355 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { makeTracer } from '@agoric/internal'; | ||
import { Fail } from '@endo/errors'; | ||
import { M } from '@endo/patterns'; | ||
import { CctpTxEvidenceShape } from '../typeGuards.js'; | ||
|
||
const trace = makeTracer('TxOperator'); | ||
|
||
/** | ||
* @import {Zone} from '@agoric/zone'; | ||
* @import {CctpTxEvidence} from '../types.js'; | ||
*/ | ||
|
||
/** | ||
* @typedef {object} OperatorStatus | ||
* @property {boolean} [disabled] | ||
* @property {string} operatorId | ||
*/ | ||
/** | ||
* @typedef {Readonly<{ operatorId: string }> & {disabled: boolean}} State | ||
*/ | ||
|
||
const OperatorKitI = { | ||
admin: M.interface('Admin', { | ||
disable: M.call().returns(), | ||
}), | ||
|
||
invitationMakers: M.interface('InvitationMakers', { | ||
SubmitEvidence: M.call(CctpTxEvidenceShape).returns(M.promise()), | ||
}), | ||
|
||
operator: M.interface('Operator', { | ||
submitEvidence: M.call(CctpTxEvidenceShape).returns(M.promise()), | ||
getStatus: M.call().returns(M.record()), | ||
}), | ||
}; | ||
|
||
/** | ||
* @param {Zone} zone | ||
* @param {{handleEvidence: Function, makeInertInvitation: Function}} powers | ||
*/ | ||
export const prepareOperatorKit = (zone, powers) => | ||
zone.exoClassKit( | ||
'Operator Kit', | ||
OperatorKitI, | ||
/** | ||
* @param {string} operatorId | ||
* @returns {State} | ||
*/ | ||
operatorId => { | ||
return { | ||
operatorId, | ||
disabled: false, | ||
}; | ||
}, | ||
{ | ||
admin: { | ||
disable() { | ||
trace(`operator ${this.state.operatorId} disabled`); | ||
this.state.disabled = true; | ||
}, | ||
}, | ||
/** | ||
* NB: when this kit is an offer result, the smart-wallet will detect the `invitationMakers` | ||
* key and save it for future offers. | ||
*/ | ||
invitationMakers: { | ||
/** | ||
* Provide an API call in the form of an invitation maker, so that the | ||
* capability is available in the smart-wallet bridge. | ||
* | ||
* NB: The `Invitation` object is evidence that the operation took | ||
* place, rather than as a means of performing it as in the | ||
* fluxAggregator contract used for price oracles. | ||
* | ||
* @param {CctpTxEvidence} evidence | ||
* @returns {Promise<Invitation>} | ||
*/ | ||
async SubmitEvidence(evidence) { | ||
const { operator } = this.facets; | ||
await operator.submitEvidence(evidence); | ||
return powers.makeInertInvitation( | ||
'evidence was pushed in the invitation maker call', | ||
); | ||
}, | ||
}, | ||
operator: { | ||
/** | ||
* submit evidence from this operator | ||
* | ||
* @param {CctpTxEvidence} evidence | ||
*/ | ||
async submitEvidence(evidence) { | ||
const { state } = this; | ||
!state.disabled || Fail`submitEvidence for disabled operator`; | ||
const result = await powers.handleEvidence( | ||
{ | ||
operatorId: state.operatorId, | ||
}, | ||
evidence, | ||
); | ||
return result; | ||
}, | ||
/** @returns {OperatorStatus} */ | ||
getStatus() { | ||
const { state } = this; | ||
return { | ||
operatorId: state.operatorId, | ||
disabled: state.disabled, | ||
}; | ||
}, | ||
}, | ||
}, | ||
); | ||
|
||
/** @typedef {ReturnType<ReturnType<typeof prepareOperatorKit>>} OperatorKit */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { makeTracer } from '@agoric/internal'; | ||
|
||
const trace = makeTracer('ZoeUtils'); | ||
|
||
/** | ||
* Used for "continuing offer" invitations in which the caller does not need | ||
* anything in return. In those cases there is no Zoe offer safety and the | ||
* invitation making function can perform the request itself. | ||
* | ||
* But smart-wallet expects an invitation maker to make an invitation, so this | ||
* function abstracts making such an inert invitation and logs consistently when | ||
* it is used. | ||
* | ||
* When this is used by an invitation maker that performs the operation, receiving | ||
* one of these invitations is evidence that the operation took place. | ||
* | ||
* @param {ZCF} zcf | ||
* @param {string} description @see {@link ZCF.makeInvitation} | ||
* @returns {() => Promise<Invitation>} an arg-less invitation maker | ||
*/ | ||
export const defineInertInvitation = (zcf, description) => { | ||
return () => | ||
zcf.makeInvitation(seat => { | ||
trace(`ℹ️ An offer was made on an inert invitation for ${description}`); | ||
seat.exit(); | ||
return 'inert; nothing should be expected from this offer'; | ||
}, description); | ||
}; |
Oops, something went wrong.