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

feat: publish vote results from the voteCounter #6204

Merged
merged 5 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
23 changes: 21 additions & 2 deletions packages/governance/src/binaryVoteCounter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { Far } from '@endo/marshal';
import { makePromiseKit } from '@endo/promise-kit';
import { makeHeapFarInstance, keyEQ, makeStore } from '@agoric/store';
import { E } from '@endo/eventual-send';

import {
buildUnrankedQuestion,
Expand Down Expand Up @@ -53,7 +54,12 @@ const validateBinaryQuestionSpec = questionSpec => {
// independently. The standard Zoe start function is at the bottom of this file.

/** @type {BuildVoteCounter} */
const makeBinaryVoteCounter = (questionSpec, threshold, instance) => {
const makeBinaryVoteCounter = (
questionSpec,
threshold,
instance,
publisher,
) => {
validateBinaryQuestionSpec(questionSpec);

const question = buildUnrankedQuestion(questionSpec, instance);
Expand Down Expand Up @@ -113,6 +119,12 @@ const makeBinaryVoteCounter = (questionSpec, threshold, instance) => {

if (!makeQuorumCounter(threshold).check(stats)) {
outcomePromise.reject('No quorum');
const voteOutcome = {
question: details.questionHandle,
outcome: 'No quorum',
};
// @ts-expect-error Expand type to allow non-position?
Copy link
Member

@turadg turadg Sep 15, 2022

Choose a reason for hiding this comment

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

yes, we should. I pushed e93c279

E(publisher).publish(voteOutcome);
return;
}

Expand All @@ -123,6 +135,12 @@ const makeBinaryVoteCounter = (questionSpec, threshold, instance) => {
} else {
outcomePromise.resolve(questionSpec.tieOutcome);
}

// XXX if we should distinguish ties, publish should be called in if above
Copy link
Member

@turadg turadg Sep 15, 2022

Choose a reason for hiding this comment

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

This would be good too but I don't object to leaving this tech debt for later. If you want to do it now, e93c279 shows how.

E.when(outcomePromise.promise, outcome => {
const voteOutcome = { question: details.questionHandle, outcome };
return E(publisher).publish(voteOutcome);
});
};

const closeFacet = makeHeapFarInstance(
Expand Down Expand Up @@ -198,7 +216,7 @@ const makeBinaryVoteCounter = (questionSpec, threshold, instance) => {
/**
* @type {ContractStartFn<VoteCounterPublicFacet, VoteCounterCreatorFacet, {questionSpec: QuestionSpec, quorumThreshold: bigint}>}
*/
const start = zcf => {
const start = (zcf, { outcomesPublisher }) => {
Copy link
Member

Choose a reason for hiding this comment

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

Practically every publisher publishes more than once so the "s" plurality for that isn't informative. What is informative is what each thing they publish is. (That helps to distinguish from when each publication is not unary.)

In this case, outcomePublisher.

// There are a variety of ways of counting quorums. The parameters must be
// visible in the terms. We're doing a simple threshold here. If we wanted to
// discount abstentions, we could refactor to provide the quorumCounter as a
Expand All @@ -210,6 +228,7 @@ const start = zcf => {
questionSpec,
quorumThreshold,
zcf.getInstance(),
outcomesPublisher,
);

scheduleClose(questionSpec.closingRule, () => closeFacet.closeVoting());
Expand Down
19 changes: 15 additions & 4 deletions packages/governance/src/committee.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ const start = (zcf, privateArgs) => {
const allQuestions = makeStore('Question');
assert(privateArgs?.storageNode, 'Missing storageNode');
assert(privateArgs?.marshaller, 'Missing marshaller');
const questionNode = E(privateArgs.storageNode).makeChildNode(
'latestQuestion',
);
/** @type {StoredPublishKit<QuestionDetails>} */
const { subscriber: questionsSubscriber, publisher: questionsPublisher } =
makeStoredPublishKit(
E(privateArgs.storageNode).makeChildNode('latestQuestion'),
privateArgs.marshaller,
);
makeStoredPublishKit(questionNode, privateArgs.marshaller);

const makeCommitteeVoterInvitation = index => {
/** @type {OfferHandler} */
Expand Down Expand Up @@ -158,13 +158,24 @@ const start = (zcf, privateArgs) => {
}
};

const outcomeNode = E(privateArgs.storageNode).makeChildNode(
'latestOutcome',
Copy link
Member

Choose a reason for hiding this comment

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

a little hesitant to have a node for each of these but feels right to error on the side of more nodes so we don't create backwards compatibility problems for any nodes with broader responsibilities.

);

/** @type {StoredPublishKit<{question: Handle<'Question'>,outcome: Position}>} */
const { publisher: outcomesPublisher } = makeStoredPublishKit(
outcomeNode,
privateArgs.marshaller,
);

return startCounter(
zcf,
questionSpec,
quorumThreshold(questionSpec.quorumRule),
voteCounter,
allQuestions,
questionsPublisher,
outcomesPublisher,
);
},
getVoterInvitations() {
Expand Down
7 changes: 4 additions & 3 deletions packages/governance/src/electorateTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const startCounter = async (
quorumThreshold,
voteCounter,
questionStore,
publisher,
questionsPublisher,
outcomesPublisher,
) => {
const voteCounterTerms = {
questionSpec,
Expand All @@ -26,10 +27,10 @@ const startCounter = async (
/** @type {{ creatorFacet: VoteCounterCreatorFacet, publicFacet: VoteCounterPublicFacet, instance: Instance }} */
const { creatorFacet, publicFacet, instance } = await E(
zcf.getZoeService(),
).startInstance(voteCounter, {}, voteCounterTerms);
).startInstance(voteCounter, {}, voteCounterTerms, { outcomesPublisher });
const details = await E(publicFacet).getDetails();
const { deadline } = questionSpec.closingRule;
publisher.publish(details);
questionsPublisher.publish(details);
const questionHandle = details.questionHandle;

const voteCounterFacets = { voteCap: creatorFacet, publicFacet, deadline };
Expand Down
1 change: 1 addition & 0 deletions packages/governance/src/internalTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
* @param {ERef<Installation>} voteCounter
* @param {Store<Handle<'Question'>, QuestionRecord>} questionStore
* @param {Publisher<unknown>} publisher
* @param {Publisher<{question: Handle<'Question'>,outcome: Position}>} storageNode`
* @returns {AddQuestionReturn}
*/
1 change: 1 addition & 0 deletions packages/governance/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@
* @param {bigint} threshold - questionSpec includes quorumRule; the electorate
* converts that to a number that the counter can enforce.
* @param {Instance} instance
* @param {ERef<Publisher<{question: Handle<'Question'>,outcome: Position}>>} publisher
* @returns {VoteCounterFacets}
*/

Expand Down
Loading