View Javadoc
1   package civitas.common.ballotdesign.tests;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertThrows;
5   import static org.mockito.Mockito.verify;
6   
7   import org.junit.jupiter.api.DisplayName;
8   import org.junit.jupiter.api.Test;
9   import org.mockito.InjectMocks;
10  import org.mockito.Mock;
11  
12  import civitas.common.ballotdesign.CalculateBallotLength;
13  import civitas.common.ballotdesign.CalculatePositionInBallot;
14  import civitas.common.ballotdesign.DecomposeBallot;
15  import civitas.common.capabilityencryption.EncryptCapability;
16  import civitas.common.encryptedchoice.EncryptChoice;
17  import civitas.common.tests.RandomAwareTestBase;
18  import civitas.common.votersubmission.VoterSubmission;
19  import civitas.common.votersubmission.tests.VoterSubmissionTestData;
20  import civitas.crypto.oneoflreencryption.tests.ElGamal1OfLReencryptionTestData;
21  import civitas.crypto.proofvote.ConstructProofVote;
22  
23  class DecomposeBallotTest extends RandomAwareTestBase
24  		implements VoterSubmissionTestData, ElGamal1OfLReencryptionTestData {
25  
26  	@InjectMocks
27  	DecomposeBallot decomposeBallot;
28  
29  	@Mock
30  	EncryptCapability encryptCapability;
31  
32  	@Mock
33  	EncryptChoice encryptChoice;
34  
35  	@Mock
36  	CalculatePositionInBallot calculatePositionInBallot;
37  
38  	@Mock
39  	ConstructProofVote constructProofVote;
40  
41  	@Mock
42  	CalculateBallotLength calculateBallotLength;
43  
44  	@Test
45  	@DisplayName(
46  			"""
47  			Decomposes a ballot into a VoterSubmission
48  			- calculates the length of the ballot based on the number of candidates
49  			- for each pair i,j:
50  			- calculates their position in the matrix
51  			- computes the encrypted choice by constructing an 1 of L reeencryption
52  			- encrypts the capability from the map
53  			- constructs a vote proof using all the above
54  			- creates a verifiable vote using the context, the encryted capability and choice and the proof
55  			- returns a voter submission for the voter block with the verifiable votes
56  			""")
57  	void test() {
58  		VoterSubmission actual = decomposeBallot.apply(
59  				BALLOTDESIGN,
60  				BALLOT,
61  				VOTER_BLOCK,
62  				EL_GAMAL_PUBLIC_KEY_E,
63  				CIPHERTEXT_LIST,
64  				ADDITIONALENV,
65  				CAPABILITY_MAP);
66  		assertEquals(VOTER_SUBMISSION, actual);
67  		verify(calculateBallotLength).apply(BALLOT.k);
68  		CalculatePositionInBallot posStub = CalculatePositionInBallotStub.stub();
69  		for (int i = 0; i < NUM_CANDIDATES; i++) {
70  			for (int j = i + 1; j < NUM_CANDIDATES; j++) {
71  				Integer pos = posStub.apply(i, j, NUM_CANDIDATES);
72  				verify(encryptCapability).apply(EL_GAMAL_PUBLIC_KEY_E, CAPABILITY_MAP, CONTEXT_0);
73  				verify(encryptChoice).apply(EL_GAMAL_PUBLIC_KEY_E, CIPHERTEXT_LIST, BALLOT.matrix, pos);
74  				verify(calculatePositionInBallot).apply(i, j, NUM_CANDIDATES);
75  
76  				verify(constructProofVote)
77  						.apply(
78  								EL_GAMAL_PARAMETERS,
79  								ENCRYPTED_SIGNED_VOTE_CAPABILITIES.get(pos),
80  								EL_GAMAL_1_OF_L_REENCRYPTION_MAP
81  										.get(BALLOT.matrix[pos])
82  										.m(),
83  								CONTEXT_MAP.get(pos),
84  								ELGAMAL_REENCRYPT_FACTOR_E,
85  								ELGAMAL_REENCRYPT_FACTOR_EPRIME);
86  			}
87  		}
88  	}
89  
90  	@Test
91  	@DisplayName("if the key is null, IllegalArgumentException is thrown")
92  	void test1() {
93  		assertThrows(
94  				IllegalArgumentException.class,
95  				() -> decomposeBallot.apply(
96  						BALLOTDESIGN, BALLOT, VOTER_BLOCK, null, CIPHERTEXT_LIST, ADDITIONALENV, CAPABILITY_MAP));
97  	}
98  
99  	@Test
100 	@DisplayName("if the number of candidates in the ballot does not match the number of candidates,"
101 			+ "IllegalArgumentException is thrown")
102 	void test2() {
103 		assertThrows(
104 				IllegalArgumentException.class,
105 				() -> decomposeBallot.apply(
106 						BALLOTDESIGN,
107 						BALLOT_2_CANDIDATES,
108 						VOTER_BLOCK,
109 						EL_GAMAL_PUBLIC_KEY_E,
110 						CIPHERTEXT_LIST,
111 						ADDITIONALENV,
112 						CAPABILITY_MAP));
113 	}
114 
115 	@Test
116 	@DisplayName("if the matrix length in the ballot does not match the number of candidates,"
117 			+ "IllegalArgumentException is thrown")
118 	void test3() {
119 		assertThrows(
120 				IllegalArgumentException.class,
121 				() -> decomposeBallot.apply(
122 						BALLOTDESIGN,
123 						BALLOT_SHORT_MATRIX,
124 						VOTER_BLOCK,
125 						EL_GAMAL_PUBLIC_KEY_E,
126 						CIPHERTEXT_LIST,
127 						ADDITIONALENV,
128 						CAPABILITY_MAP));
129 	}
130 }