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

[TECH-471] VotingRounds #210

Merged
merged 6 commits into from
Dec 6, 2022
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
26 changes: 21 additions & 5 deletions lib/av_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { OTPProvider, IdentityConfirmationToken } from "./av_client/connectors/o
import { extractContestSelections } from './util/nist_cvr_extractor';
import { AVVerifier } from './av_verifier';
import { constructContestEnvelopes } from './av_client/construct_contest_envelopes';
import { KeyPair, Affidavit, VerifierItem, CommitmentOpening, SpoilRequestItem, LatestConfig, BallotSelection, ContestEnvelope, BallotConfig, BallotStatus } from './av_client/types';
import { KeyPair, Affidavit, VerifierItem, CommitmentOpening, SpoilRequestItem, LatestConfig, BallotSelection, ContestEnvelope, BallotConfig, BallotStatus, ContestConfig } from './av_client/types';
import { randomKeyPair } from './av_client/generate_key_pair';
import { generateReceipt } from './av_client/generate_receipt';
import * as jwt from 'jose';
Expand Down Expand Up @@ -86,6 +86,7 @@ export const sjcl = sjclLib;
export class AVClient implements IAVClient {
private authorizationSessionId: string;
private email: string;
private votingRoundReference: string;
private identityConfirmationToken: IdentityConfirmationToken;
private dbbPublicKey: string | undefined;

Expand Down Expand Up @@ -200,12 +201,13 @@ export class AVClient implements IAVClient {
* Registers a voter based on the authorization mode of the Voter Authorizer
* Authorization is done by 'proof-of-identity' or 'proof-of-election-codes'
*/
public async createVoterRegistration(): Promise<void> {
public async createVoterRegistration(votingRoundReference = "voting-round-1"): Promise<void> {
const coordinatorURL = this.getLatestConfig().items.voterAuthorizerConfig.content.voterAuthorizer.url;
const voterAuthorizerContextUuid = this.getLatestConfig().items.voterAuthorizerConfig.content.voterAuthorizer.contextUuid;
const coordinator = new VoterAuthorizationCoordinator(coordinatorURL, voterAuthorizerContextUuid);
const latestConfigAddress = this.getLatestConfig().items.latestConfigItem.address;
const authorizationMode = this.getLatestConfig().items.voterAuthorizerConfig.content.voterAuthorizer.authorizationMode;
this.votingRoundReference = votingRoundReference

let authorizationResponse: AxiosResponse

Expand Down Expand Up @@ -238,7 +240,8 @@ export class AVClient implements IAVClient {
identifier: decoded['identifier'],
publicKey: decoded['public_key'],
weight: decoded['weight'] || 1,
voterGroup: decoded['voter_group_key']
voterGroup: decoded['voter_group_key'],
votingRoundReference: decoded['voting_round_reference']
}
}

Expand Down Expand Up @@ -299,7 +302,7 @@ export class AVClient implements IAVClient {
* Should be followed by either {@link AVClient.spoilBallot | spoilBallot}
* or {@link AVClient.castBallot | castBallot}.
*
* @param cvr Object containing the selections for each contest.
* @param ballotSelection BallotSelection containing the selections for each contest.
* @returns Returns the ballot tracking code. Example:
* ```javascript
* '5e4d8fe41fa3819cc064e2ace0eda8a847fe322594a6fd5a9a51c699e63804b7'
Expand Down Expand Up @@ -510,6 +513,18 @@ export class AVClient implements IAVClient {
return ballotConfigs[voterSession.content.voterGroup]
}

public getVoterContestConfigs(): ContestConfig[] {
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is this method used?

Copy link
Contributor

Choose a reason for hiding this comment

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

It is not used in JS-client, but I asked @av-mads yesterday, and he told me that it is supposed to be used by calling it from outside (instances of AVclient I'd guess).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's used by liminal I think. May also be used elsewhere

const voterSession = this.getVoterSession()
const { items: { ballotConfigs, votingRoundConfigs, contestConfigs }} = this.getLatestConfig()

const myBallotConfig = ballotConfigs[voterSession.content.voterGroup]
const myVotingRoundConfig = votingRoundConfigs[voterSession.content.votingRoundReference]
const contestsICanVoteOn = myBallotConfig.content.contestReferences.filter(value => myVotingRoundConfig.contestReferences.includes(value));
return contestsICanVoteOn.map(contestReference => {
return contestConfigs[contestReference]
})
}

public getDbbPublicKey(): string {
const dbbPublicKeyFromConfig = this.getLatestConfig().items.genesisConfig.content.publicKey;

Expand All @@ -535,7 +550,8 @@ export class AVClient implements IAVClient {
return await coordinator.requestPublicKeyAuthorization(
this.authorizationSessionId,
this.identityConfirmationToken,
this.keyPair.publicKey
this.keyPair.publicKey,
this.votingRoundReference
);
}

Expand Down
5 changes: 3 additions & 2 deletions lib/av_client/connectors/voter_authorization_coordinator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ export default class VoterAuthorizationCoordinator {
});
}

requestPublicKeyAuthorization(sessionId: string, identityConfirmationToken: IdentityConfirmationToken, publicKey: string): Promise<AxiosResponse> {
requestPublicKeyAuthorization(sessionId: string, identityConfirmationToken: IdentityConfirmationToken, publicKey: string, votingRoundReference: string): Promise<AxiosResponse> {
return this.backend.post('request_authorization', {
electionContextUuid: this.electionContextUuid,
sessionId: sessionId,
emailConfirmationToken: identityConfirmationToken,
publicKey: publicKey
publicKey: publicKey,
votingRoundReference: votingRoundReference
})
}

Expand Down
12 changes: 10 additions & 2 deletions lib/av_client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export interface VoterSessionItem extends BaseBoardItem {
identifier: string
voterGroup: string
publicKey: string
votingRoundReference: string
}

type: "VoterSessionItem"
Expand Down Expand Up @@ -279,7 +280,7 @@ export interface LatestConfigItems {
voterAuthorizerConfig: VoterAuthorizer;
ballotConfigs: BallotConfigMap;
contestConfigs: ContestConfigMap;
// votingRoundConfigs: VotingRoundConfig[];
votingRoundConfigs: VotingRoundConfigMap;
electionConfig: ElectionConfig;
genesisConfig: GenesisConfig;
latestConfigItem: BaseBoardItem;
Expand Down Expand Up @@ -364,7 +365,14 @@ export interface OptionContent {
}

// Voting Round Config Item
// export type VotingRoundConfig = {}
export type VotingRoundConfigMap = {
[votingRoundReference: string]: VotingRoundConfig
}

export type VotingRoundConfig = {
reference: string
contestReferences: string[]
}

// Election Config Item
export type ElectionConfig = {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aion-dk/js-client",
"version": "2.0.1",
"version": "2.0.2",
"license": "MIT",
"description": "Assembly Voting JS client",
"main": "dist/lib/av_client.js",
Expand Down
4 changes: 2 additions & 2 deletions test/benaloh_flow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ describe.skip('entire benaloh flow', () => {
}).timeout(10000);

async function placeVote(client: AVClient) {
const voterId = 'B00000000001';
const voterEmail = 'markitmarchtest@osetinstitute.org'
const voterId = Math.random().toString();
const voterEmail = 'dev@assemblyvoting.com'
await client.requestAccessCode(voterId, voterEmail).catch((e) => {
console.error(e);
});
Expand Down
1 change: 1 addition & 0 deletions test/construct_contest_envelopes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const clientState: ClientState = {
electionConfig: latestConfig.items.electionConfig,
genesisConfig: latestConfig.items.genesisConfig,
latestConfigItem: latestConfig.items.latestConfigItem,
votingRoundConfigs: latestConfig.items.votingRoundConfigs
}
},
voterSession: {
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/latestConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ const latestConfig: LatestConfig = {
},
uuid: "bc1b1ed0-943e-4647-bfc1-0633ba08c05e",
}
},
votingRoundConfigs: {

},
genesisConfig: {
content: {
Expand Down
3 changes: 2 additions & 1 deletion test/validation_checks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ describe('Validation checks', () => {
authToken: "",
identifier: "",
voterGroup: "",
publicKey: publicKey
publicKey: publicKey,
votingRoundReference: ""
},
registeredAt: "",
signature: "71b8d5d9565d7a174cc2938b1a591281538bbbd913032ff87f7d92071e01f335,70cef6d1f4d1ef06f5a1a207c70dcd936a2c6fb508361e61cf4c77aa1175319d",
Expand Down
8 changes: 1 addition & 7 deletions test/walkthrough.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,14 @@ describe.skip('entire voter flow using OTP authorization', () => {
});

it('returns a receipt', async () => {
const _performTest = async () => {
const client = new AVClient(bulletinBoardHost + 'us');
await client.initialize(undefined, {
privateKey: 'bcafc67ca4af6b462f60d494adb675d8b1cf57b16dfd8d110bbc2453709999b0',
publicKey: '03b87d7fe793a621df27f44c20f460ff711d55545c58729f20b3fb6e871c53c49c'
});

const voterId = Math.random().toString()
const voterEmail = 'markitmarchtest@osetinstitute.org'
const voterEmail = 'dev@assemblyvoting.com'
await client.requestAccessCode(voterId, voterEmail).catch((e) => {
console.error(e);
expect.fail('AVClient#requestAccessCode failed.');
Expand Down Expand Up @@ -58,8 +57,6 @@ describe.skip('entire voter flow using OTP authorization', () => {
const receipt = await client.castBallot(affidavit);
expect(receipt.trackingCode.length).to.eql(7);

await _performTest();
}
}).timeout(10000);

async function extractOTPFromEmail() {
Expand Down Expand Up @@ -99,7 +96,6 @@ describe.skip('entire voter flow using PoEC authorization', () => {
});

it('returns a receipt', async () => {
const _performTest = async () => {
const client = new AVClient(bulletinBoardHost + '2904b00f_5abcbf894df3_58');
await client.initialize(undefined, {
privateKey: 'bcafc67ca4af6b462f60d494adb675d8b1cf57b16dfd8d110bbc2453709999b0',
Expand All @@ -125,8 +121,6 @@ describe.skip('entire voter flow using PoEC authorization', () => {
const receipt = await client.castBallot(affidavit);
expect(receipt.trackingCode.length).to.eql(7)

await _performTest();
}
}).timeout(10000);
})

Expand Down