From 1e288e3e4a07f907dd823d1c3163f58f27313d1b Mon Sep 17 00:00:00 2001 From: KoningR Date: Tue, 31 Mar 2020 15:15:15 +0200 Subject: [PATCH 01/26] Add the initial voting functionality of the distributed democracy group to the super-app. --- .idea/.gitignore | 2 + .../common/util/TrustChainHelper.kt | 4 +- .../trustchain/common/util/VotingHelper.kt | 139 ++++++++++++++++++ 3 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..5c98b4288 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml \ No newline at end of file diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/TrustChainHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/TrustChainHelper.kt index 925c02131..6944a5edc 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/TrustChainHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/TrustChainHelper.kt @@ -42,9 +42,9 @@ class TrustChainHelper( /** * Creates a new proposal block, using a text message as the transaction content. + * Optionally, the blockType can be passed as an argument. Default value is "demo_block". */ - fun createProposalBlock(message: String, publicKey: ByteArray) { - val blockType = "demo_block" + fun createProposalBlock(message: String, publicKey: ByteArray, blockType: String = "demo_block") { val transaction = mapOf("message" to message) trustChainCommunity.createProposalBlock(blockType, transaction, publicKey) } diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt new file mode 100644 index 000000000..c1ed1c53e --- /dev/null +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -0,0 +1,139 @@ +package nl.tudelft.trustchain.common.util + +import android.util.Log +import nl.tudelft.ipv8.android.IPv8Android +import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock +import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity +import nl.tudelft.ipv8.keyvault.PublicKey +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import java.util.* + +class VotingHelper { + private val votingBlock = "voting_block" + + private val trustchain: TrustChainHelper by lazy { + TrustChainHelper(getTrustChainCommunity()) + } + + fun startVote(voteSubject: String, peers: List, self: PublicKey) { + // TODO: Add vote ID to increase probability of uniqueness. + + // Get all peers in the community and create a JSON array of their public keys. + val voteList = JSONArray(peers.map { it.toString() }) + + // Create a JSON object containing the vote subject + val voteJSON = JSONObject() + .put("VOTE_SUBJECT", voteSubject) + .put("VOTE_LIST", voteList) + + // Put the JSON string in the transaction's 'message' field. + val transaction = voteJSON.toString() + + // Loop through all peers in the voting community and send a proposal. + for (peer in peers) { + trustchain.createProposalBlock(transaction, peer.keyToBin(), blockType = votingBlock) + } + + // Update the JSON to include a VOTE_END message. + voteJSON.put("VOTE_END", "True") + val endTransaction = voteJSON.toString() + + trustchain.createProposalBlock(endTransaction, self.keyToBin(), votingBlock) + } + + fun respondToVote(voteName: String, vote: Boolean, proposalBlock: TrustChainBlock) { + // Reply to the vote with YES or NO. + val voteReply = if (vote) "YES" else "NO" + + // Create a JSON object containing the vote subject and the reply. + val voteJSON = JSONObject() + .put("VOTE_SUBJECT", voteName) + .put("VOTE_REPLY", voteReply) + + // Put the JSON string in the transaction's 'message' field. + val transaction = mapOf("message" to voteJSON.toString()) + + trustchain.createAgreementBlock(proposalBlock, transaction) + } + + /** + * Return the tally on a vote proposal in a pair(yes, no). + */ + fun countVotes(voteName: String, proposerKey: ByteArray): Pair { + + val voters: MutableList = ArrayList() + + var yesCount = 0 + var noCount = 0 + + // Crawl the chain of the proposer. + for (it in trustchain.getChainByUser(proposerKey)) { + + if (voters.contains(it.publicKey.contentToString())){ + continue + } + + // Skip all blocks which are not voting blocks + // and don't have a 'message' field in their transaction. + if (it.type != "voting_block" || !it.transaction.containsKey("message")) { + continue + } + + // Parse the 'message' field as JSON. + val voteJSON = try { + JSONObject(it.transaction["message"].toString()) + } catch (e: JSONException) { + // Assume a malicious vote if it claims to be a vote but does not contain + // proper JSON. + handleInvalidVote("Block was a voting block but did not contain " + + "proper JSON in its message field: ${it.transaction["message"].toString()}." + ) + continue + } + + // Assume a malicious vote if it does not have a VOTE_SUBJECT. + if (!voteJSON.has("VOTE_SUBJECT")) { + handleInvalidVote("Block type was a voting block but did not have a VOTE_SUBJECT.") + continue + } + + // A block with another VOTE_SUBJECT belongs to another vote. + if (voteJSON.get("VOTE_SUBJECT") != voteName) { + // Block belongs to another vote. + continue + } + + // A block with the same subject but no reply is the original vote proposal. + if (!voteJSON.has("VOTE_REPLY")) { + // Block is the initial vote proposal because it does not have a VOTE_REPLY field. + continue + } + + // Add the votes, or assume a malicious vote if it is not YES or NO. + when (voteJSON.get("VOTE_REPLY")) { + "YES" -> { + yesCount++ + voters.add(it.publicKey.contentToString()) + } + "NO" -> { + noCount++ + voters.add(it.publicKey.contentToString()) + } + else -> handleInvalidVote("Vote was not 'YES' or 'NO' but: '${voteJSON.get("VOTE_REPLY")}'.") + } + } + + return Pair(yesCount, noCount) + } + + private fun handleInvalidVote(errorType: String) { + Log.e("vote_debug", errorType) + } + + private fun getTrustChainCommunity(): TrustChainCommunity { + return IPv8Android.getInstance().getOverlay() + ?: throw IllegalStateException("TrustChainCommunity is not configured") + } +} From 51f5e29aeb7f5c39af38e25af8de200de999e6e4 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Thu, 2 Apr 2020 12:17:42 +0200 Subject: [PATCH 02/26] Extended git ignore to include the `.idea` folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 378eac25d..b7c1c7e8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build +.idea \ No newline at end of file From 2cc199bfee8323899a615b4cded7f2583e8529cd Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Thu, 2 Apr 2020 12:58:30 +0200 Subject: [PATCH 03/26] Extended git ignore to include the `.idea` folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 378eac25d..b7c1c7e8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build +.idea \ No newline at end of file From 38dcc3e03540478a890968dd9d1fd1ca6d656eac Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Thu, 2 Apr 2020 13:02:18 +0200 Subject: [PATCH 04/26] Removed the idea folder from git --- .idea/.gitignore | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .idea/.gitignore diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 5c98b4288..000000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Default ignored files -/workspace.xml \ No newline at end of file From f08e43e6216381eb3989a959d3830290d22c504d Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Thu, 2 Apr 2020 20:22:32 +0200 Subject: [PATCH 05/26] Update start vote method to use new api-approach --- .../trustchain/common/util/VotingHelper.kt | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index c1ed1c53e..59823c0ec 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -2,6 +2,7 @@ package nl.tudelft.trustchain.common.util import android.util.Log import nl.tudelft.ipv8.android.IPv8Android +import nl.tudelft.ipv8.attestation.trustchain.EMPTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.keyvault.PublicKey @@ -17,30 +18,24 @@ class VotingHelper { TrustChainHelper(getTrustChainCommunity()) } + /** + * Initiate a vote amongst a set of peers + */ fun startVote(voteSubject: String, peers: List, self: PublicKey) { // TODO: Add vote ID to increase probability of uniqueness. - // Get all peers in the community and create a JSON array of their public keys. - val voteList = JSONArray(peers.map { it.toString() }) + val voteList = JSONArray(peers) - // Create a JSON object containing the vote subject + // Create a JSON object containing the vote subject, as well as a log of the eligible voters val voteJSON = JSONObject() .put("VOTE_SUBJECT", voteSubject) .put("VOTE_LIST", voteList) - // Put the JSON string in the transaction's 'message' field. val transaction = voteJSON.toString() - // Loop through all peers in the voting community and send a proposal. - for (peer in peers) { - trustchain.createProposalBlock(transaction, peer.keyToBin(), blockType = votingBlock) - } - - // Update the JSON to include a VOTE_END message. - voteJSON.put("VOTE_END", "True") - val endTransaction = voteJSON.toString() + // Create any-counterpary block for the transaction + trustchain.createProposalBlock(transaction, EMPTY_PK, "voting_block") - trustchain.createProposalBlock(endTransaction, self.keyToBin(), votingBlock) } fun respondToVote(voteName: String, vote: Boolean, proposalBlock: TrustChainBlock) { From 387e9e7c12fb037eaa4a78f36b01363ca65a3832 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Thu, 2 Apr 2020 20:29:45 +0200 Subject: [PATCH 06/26] Update respond to vote and countvote to account for any counterparty. --- .../trustchain/common/util/VotingHelper.kt | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index 59823c0ec..d571e6011 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -6,6 +6,7 @@ import nl.tudelft.ipv8.attestation.trustchain.EMPTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.keyvault.PublicKey +import nl.tudelft.ipv8.keyvault.defaultCryptoProvider import org.json.JSONArray import org.json.JSONException import org.json.JSONObject @@ -34,10 +35,14 @@ class VotingHelper { val transaction = voteJSON.toString() // Create any-counterpary block for the transaction - trustchain.createProposalBlock(transaction, EMPTY_PK, "voting_block") + trustchain.createProposalBlock(transaction, EMPTY_PK, votingBlock) } + + /** + * Respond to a proposal block on the trustchain, either agree with "YES" or disagree "NO" + */ fun respondToVote(voteName: String, vote: Boolean, proposalBlock: TrustChainBlock) { // Reply to the vote with YES or NO. val voteReply = if (vote) "YES" else "NO" @@ -53,26 +58,29 @@ class VotingHelper { trustchain.createAgreementBlock(proposalBlock, transaction) } + /** * Return the tally on a vote proposal in a pair(yes, no). */ - fun countVotes(voteName: String, proposerKey: ByteArray): Pair { - - val voters: MutableList = ArrayList() + fun countVotes(voters: List, voteName: String, proposerKey: ByteArray): Pair { + // ArrayList for keeping track of already counted votes + val votes: MutableList = ArrayList() var yesCount = 0 var noCount = 0 // Crawl the chain of the proposer. for (it in trustchain.getChainByUser(proposerKey)) { + val blockPublicKey = defaultCryptoProvider.keyFromPublicBin(it.publicKey).toString() - if (voters.contains(it.publicKey.contentToString())){ + // Check whether vote has already been counted + if (votes.contains(it.publicKey.contentToString())) { continue } // Skip all blocks which are not voting blocks // and don't have a 'message' field in their transaction. - if (it.type != "voting_block" || !it.transaction.containsKey("message")) { + if (it.type != votingBlock || !it.transaction.containsKey("message")) { continue } @@ -82,8 +90,9 @@ class VotingHelper { } catch (e: JSONException) { // Assume a malicious vote if it claims to be a vote but does not contain // proper JSON. - handleInvalidVote("Block was a voting block but did not contain " + - "proper JSON in its message field: ${it.transaction["message"].toString()}." + handleInvalidVote( + "Block was a voting block but did not contain " + + "proper JSON in its message field: ${it.transaction["message"].toString()}." ) continue } @@ -106,15 +115,20 @@ class VotingHelper { continue } + // Check whether the voter is in voting list + if (!voters.contains(blockPublicKey)) { + continue + } + // Add the votes, or assume a malicious vote if it is not YES or NO. when (voteJSON.get("VOTE_REPLY")) { "YES" -> { yesCount++ - voters.add(it.publicKey.contentToString()) + votes.add(it.publicKey.contentToString()) } "NO" -> { noCount++ - voters.add(it.publicKey.contentToString()) + votes.add(it.publicKey.contentToString()) } else -> handleInvalidVote("Vote was not 'YES' or 'NO' but: '${voteJSON.get("VOTE_REPLY")}'.") } From fcba8702e0f23fc96d71e8f153fff5f69c0dc8f8 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Thu, 2 Apr 2020 22:38:58 +0200 Subject: [PATCH 07/26] Initial test setup, updated gradle --- common/build.gradle | 6 ++ .../trustchain/common/util/VotingHelper.kt | 3 +- .../trustchain/common/ExampleUnitTest.kt | 2 + .../common/util/VotingHelperTest.kt | 98 +++++++++++++++++++ 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt diff --git a/common/build.gradle b/common/build.gradle index 6589907a2..1eba39495 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -46,6 +46,7 @@ android { dependencies { api project(':ipv8-android') + api project(':ipv8') // AndroidX implementation 'androidx.appcompat:appcompat:1.1.0' @@ -76,8 +77,13 @@ dependencies { implementation 'com.mattskala:itemadapter:0.3' + // Crypto + implementation "com.goterl.lazycode:lazysodium-java:4.2.4" + // Testing testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.3' + testImplementation "io.mockk:mockk:1.9.3" } diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index d571e6011..da5ae8a48 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -22,7 +22,7 @@ class VotingHelper { /** * Initiate a vote amongst a set of peers */ - fun startVote(voteSubject: String, peers: List, self: PublicKey) { + fun startVote(voteSubject: String, peers: List) { // TODO: Add vote ID to increase probability of uniqueness. val voteList = JSONArray(peers) @@ -63,6 +63,7 @@ class VotingHelper { * Return the tally on a vote proposal in a pair(yes, no). */ fun countVotes(voters: List, voteName: String, proposerKey: ByteArray): Pair { + // ArrayList for keeping track of already counted votes val votes: MutableList = ArrayList() diff --git a/common/src/test/java/nl/tudelft/trustchain/common/ExampleUnitTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/ExampleUnitTest.kt index 7a4fc2e44..961cb5ed8 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/ExampleUnitTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/ExampleUnitTest.kt @@ -15,3 +15,5 @@ class ExampleUnitTest { assertEquals(4, 2 + 2) } } + + diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt new file mode 100644 index 000000000..b96dd1c1d --- /dev/null +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -0,0 +1,98 @@ +import com.goterl.lazycode.lazysodium.LazySodiumJava +import com.goterl.lazycode.lazysodium.SodiumJava +import io.mockk.mockk +import io.mockk.spyk +import io.mockk.verify +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestCoroutineDispatcher +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.setMain +import nl.tudelft.ipv8.Peer +import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity +import nl.tudelft.ipv8.attestation.trustchain.TrustChainSettings +import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore +import nl.tudelft.ipv8.keyvault.JavaCryptoProvider +import nl.tudelft.ipv8.keyvault.LibNaClSK +import nl.tudelft.ipv8.keyvault.PrivateKey +import nl.tudelft.ipv8.keyvault.PublicKey +import nl.tudelft.ipv8.messaging.EndpointAggregator +import nl.tudelft.ipv8.peerdiscovery.Network +import nl.tudelft.ipv8.util.hexToBytes +import nl.tudelft.trustchain.common.util.VotingHelper +import org.junit.After +import org.junit.Before +import org.junit.Test + +private val lazySodium = LazySodiumJava(SodiumJava()) + +class VotingHelperTest { + + private val votingHelper = VotingHelper() + + private fun getCommunity(): TrustChainCommunity { + val settings = TrustChainSettings() + val store = mockk(relaxed = true) + val community = TrustChainCommunity(settings = settings, database = store) + community.myPeer = getMyPeer() + community.endpoint = getEndpoint() + community.network = Network() + community.maxPeers = 20 + community.cryptoProvider = JavaCryptoProvider + community.load() + return community + } + + private val testDispatcher = TestCoroutineDispatcher() + + @ExperimentalCoroutinesApi + @Before + fun setUp() { + Dispatchers.setMain(testDispatcher) + } + + @After + fun tearDown() { + Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher + testDispatcher.cleanupTestCoroutines() + } + + protected fun getPrivateKey(): PrivateKey { + val privateKey = "81df0af4c88f274d5228abb894a68906f9e04c902a09c68b9278bf2c7597eaf6" + val signSeed = "c5c416509d7d262bddfcef421fc5135e0d2bdeb3cb36ae5d0b50321d766f19f2" + return LibNaClSK(privateKey.hexToBytes(), signSeed.hexToBytes(), lazySodium) + } + + protected fun getMyPeer(): Peer { + return Peer(getPrivateKey()) + } + + protected fun getEndpoint(): EndpointAggregator { + return spyk(EndpointAggregator(mockk(relaxed = true), null)) + } + + + + @Test + fun startVote() { + val community = getCommunity() + + // Create list of your peers and include yourself + val peers: MutableList = ArrayList() + peers.addAll(community.getPeers().map { it.publicKey }) + peers.add(community.myPeer.publicKey) + + votingHelper.startVote("There should be tests", peers) + + // Placeholder, should test if vote proposal block is present + verify { 1 == 1 } + } + + @Test + fun respondToVote() { + } + + @Test + fun countVotes() { + } +} From 27d5dc9faf3c90f4f89d8d3df04e79896e20507e Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 11:28:27 +0200 Subject: [PATCH 08/26] Improved documentation for the other groups to use --- .../trustchain/common/util/VotingHelper.kt | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index da5ae8a48..29405da4f 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -20,7 +20,9 @@ class VotingHelper { } /** - * Initiate a vote amongst a set of peers + * Initiate a vote amongst a set of peers. + * @param voteSubject the matter to be voted upon. + * @param peers list of the public keys of those eligible to vote. */ fun startVote(voteSubject: String, peers: List) { // TODO: Add vote ID to increase probability of uniqueness. @@ -41,15 +43,18 @@ class VotingHelper { /** - * Respond to a proposal block on the trustchain, either agree with "YES" or disagree "NO" + * Respond to a proposal block on the trustchain, either agree with "YES" or disagree "NO". + * @param voteSubject the matter to be voted upon. + * @param vote boolean value indicating the decision. + * @param proposalBlock TrustChainBlock of the proposalblock. */ - fun respondToVote(voteName: String, vote: Boolean, proposalBlock: TrustChainBlock) { + fun respondToVote(voteSubject: String, vote: Boolean, proposalBlock: TrustChainBlock) { // Reply to the vote with YES or NO. val voteReply = if (vote) "YES" else "NO" // Create a JSON object containing the vote subject and the reply. val voteJSON = JSONObject() - .put("VOTE_SUBJECT", voteName) + .put("VOTE_SUBJECT", voteSubject) .put("VOTE_REPLY", voteReply) // Put the JSON string in the transaction's 'message' field. @@ -61,8 +66,16 @@ class VotingHelper { /** * Return the tally on a vote proposal in a pair(yes, no). + * @param voters list of the public keys of the eligible voters. + * @param voteSubject the matter to be voted upon. + * @param proposerKey the identifier of the vote proposer . + * @return Pair indicating the election results. */ - fun countVotes(voters: List, voteName: String, proposerKey: ByteArray): Pair { + fun countVotes( + voters: List, + voteSubject: String, + proposerKey: ByteArray + ): Pair { // ArrayList for keeping track of already counted votes val votes: MutableList = ArrayList() @@ -72,7 +85,7 @@ class VotingHelper { // Crawl the chain of the proposer. for (it in trustchain.getChainByUser(proposerKey)) { - val blockPublicKey = defaultCryptoProvider.keyFromPublicBin(it.publicKey).toString() + val blockPublicKey = defaultCryptoProvider.keyFromPublicBin(it.publicKey) // Check whether vote has already been counted if (votes.contains(it.publicKey.contentToString())) { @@ -105,7 +118,7 @@ class VotingHelper { } // A block with another VOTE_SUBJECT belongs to another vote. - if (voteJSON.get("VOTE_SUBJECT") != voteName) { + if (voteJSON.get("VOTE_SUBJECT") != voteSubject) { // Block belongs to another vote. continue } @@ -138,10 +151,16 @@ class VotingHelper { return Pair(yesCount, noCount) } + /** + * Helper function for debugging purposes + */ private fun handleInvalidVote(errorType: String) { Log.e("vote_debug", errorType) } + /** + * @return the TrustChainCommunity in use + */ private fun getTrustChainCommunity(): TrustChainCommunity { return IPv8Android.getInstance().getOverlay() ?: throw IllegalStateException("TrustChainCommunity is not configured") From e903b1da9ad3561c8607284dcaeba41a03986bd0 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 11:45:04 +0200 Subject: [PATCH 09/26] Made the trustchain community a param for the voting helper --- .../trustchain/common/DemoCommunity.kt | 16 ++++++++++- .../trustchain/common/util/VotingHelper.kt | 28 +++++++++---------- .../common/util/VotingHelperTest.kt | 4 +-- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt b/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt index d7de0387c..3eb86bfe1 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt @@ -2,17 +2,31 @@ package nl.tudelft.trustchain.common import nl.tudelft.ipv8.IPv4Address import nl.tudelft.ipv8.Community +import nl.tudelft.ipv8.IPv8 import nl.tudelft.ipv8.Peer +import nl.tudelft.ipv8.android.IPv8Android +import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.messaging.payload.IntroductionResponsePayload +import nl.tudelft.trustchain.common.util.TrustChainHelper +import nl.tudelft.trustchain.common.util.VotingHelper import java.util.* -class DemoCommunity : Community() { +open class DemoCommunity : Community() { override val serviceId = "02313685c1912a141279f8248fc8db5899c5df5a" val discoveredAddressesContacted: MutableMap = mutableMapOf() val lastTrackerResponses = mutableMapOf() + // Retrieve the trustchain community + private fun getTrustChainCommunity(): TrustChainCommunity { + return IPv8Android.getInstance().getOverlay() + ?: throw IllegalStateException("TrustChainCommunity is not configured") + } + + // Create a votingHelper instance for voting across the community + val votingHelper: VotingHelper = VotingHelper(getTrustChainCommunity()) + override fun walkTo(address: IPv4Address) { super.walkTo(address) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index 29405da4f..f672376b4 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -12,12 +12,17 @@ import org.json.JSONException import org.json.JSONObject import java.util.* -class VotingHelper { +/** + * Helper class for creating votes proposals, casting and counting. + * @param trustChainCommunity the community where the votes will be dealt. + */ +class VotingHelper( + trustChainCommunity: TrustChainCommunity +) { private val votingBlock = "voting_block" - private val trustchain: TrustChainHelper by lazy { - TrustChainHelper(getTrustChainCommunity()) - } + private val trustChainHelper: TrustChainHelper = TrustChainHelper(trustChainCommunity) + /** * Initiate a vote amongst a set of peers. @@ -37,7 +42,7 @@ class VotingHelper { val transaction = voteJSON.toString() // Create any-counterpary block for the transaction - trustchain.createProposalBlock(transaction, EMPTY_PK, votingBlock) + trustChainHelper.createProposalBlock(transaction, EMPTY_PK, votingBlock) } @@ -60,7 +65,7 @@ class VotingHelper { // Put the JSON string in the transaction's 'message' field. val transaction = mapOf("message" to voteJSON.toString()) - trustchain.createAgreementBlock(proposalBlock, transaction) + trustChainHelper.createAgreementBlock(proposalBlock, transaction) } @@ -84,7 +89,7 @@ class VotingHelper { var noCount = 0 // Crawl the chain of the proposer. - for (it in trustchain.getChainByUser(proposerKey)) { + for (it in trustChainHelper.getChainByUser(proposerKey)) { val blockPublicKey = defaultCryptoProvider.keyFromPublicBin(it.publicKey) // Check whether vote has already been counted @@ -151,18 +156,11 @@ class VotingHelper { return Pair(yesCount, noCount) } + /** * Helper function for debugging purposes */ private fun handleInvalidVote(errorType: String) { Log.e("vote_debug", errorType) } - - /** - * @return the TrustChainCommunity in use - */ - private fun getTrustChainCommunity(): TrustChainCommunity { - return IPv8Android.getInstance().getOverlay() - ?: throw IllegalStateException("TrustChainCommunity is not configured") - } } diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index b96dd1c1d..41512cce0 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -28,8 +28,6 @@ private val lazySodium = LazySodiumJava(SodiumJava()) class VotingHelperTest { - private val votingHelper = VotingHelper() - private fun getCommunity(): TrustChainCommunity { val settings = TrustChainSettings() val store = mockk(relaxed = true) @@ -72,10 +70,10 @@ class VotingHelperTest { } - @Test fun startVote() { val community = getCommunity() + val votingHelper = VotingHelper(community) // Create list of your peers and include yourself val peers: MutableList = ArrayList() From de77a9bae70858327b0307e7a4ab4a273dc2f23a Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 12:20:40 +0200 Subject: [PATCH 10/26] Tested start vote (NOTE, not working yet due to mock issues) --- .../trustchain/common/util/VotingHelper.kt | 3 +-- .../trustchain/common/util/VotingHelperTest.kt | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index f672376b4..314a479cc 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -1,7 +1,6 @@ package nl.tudelft.trustchain.common.util import android.util.Log -import nl.tudelft.ipv8.android.IPv8Android import nl.tudelft.ipv8.attestation.trustchain.EMPTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity @@ -41,7 +40,7 @@ class VotingHelper( val transaction = voteJSON.toString() - // Create any-counterpary block for the transaction + // Create any-counterparty block for the transaction trustChainHelper.createProposalBlock(transaction, EMPTY_PK, votingBlock) } diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index 41512cce0..d4140760f 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -19,7 +19,10 @@ import nl.tudelft.ipv8.keyvault.PublicKey import nl.tudelft.ipv8.messaging.EndpointAggregator import nl.tudelft.ipv8.peerdiscovery.Network import nl.tudelft.ipv8.util.hexToBytes +import nl.tudelft.trustchain.common.util.TrustChainHelper import nl.tudelft.trustchain.common.util.VotingHelper +import org.json.JSONException +import org.json.JSONObject import org.junit.After import org.junit.Before import org.junit.Test @@ -41,6 +44,7 @@ class VotingHelperTest { return community } + @ExperimentalCoroutinesApi private val testDispatcher = TestCoroutineDispatcher() @ExperimentalCoroutinesApi @@ -49,6 +53,7 @@ class VotingHelperTest { Dispatchers.setMain(testDispatcher) } + @ExperimentalCoroutinesApi @After fun tearDown() { Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher @@ -73,6 +78,7 @@ class VotingHelperTest { @Test fun startVote() { val community = getCommunity() + val helper = TrustChainHelper(community) val votingHelper = VotingHelper(community) // Create list of your peers and include yourself @@ -80,10 +86,15 @@ class VotingHelperTest { peers.addAll(community.getPeers().map { it.publicKey }) peers.add(community.myPeer.publicKey) - votingHelper.startVote("There should be tests", peers) + val voteSubject = "There should be tests" + votingHelper.startVote(voteSubject, peers) - // Placeholder, should test if vote proposal block is present - verify { 1 == 1 } + // Verify that the proposal block has been casted + verify { + helper.getChainByUser(community.myPeer.publicKey.keyToBin()).any { + JSONObject(it.transaction["message"].toString()).get("VOTE_SUBJECT") == voteSubject + } + } } @Test From 0d4ee2edd38891afc52a8226e15142b3984c85ec Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 13:25:28 +0200 Subject: [PATCH 11/26] retrieve voteSubject from the proposal block instead of seperate parameter for easier use. --- common/build.gradle | 4 ++++ .../tudelft/trustchain/common/util/VotingHelper.kt | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 1eba39495..f8833e671 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -42,6 +42,10 @@ android { viewBinding { enabled = true } + + testOptions { + unitTests.returnDefaultValues = true + } } dependencies { diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index 314a479cc..e1448530e 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -52,13 +52,21 @@ class VotingHelper( * @param vote boolean value indicating the decision. * @param proposalBlock TrustChainBlock of the proposalblock. */ - fun respondToVote(voteSubject: String, vote: Boolean, proposalBlock: TrustChainBlock) { + fun respondToVote(vote: Boolean, proposalBlock: TrustChainBlock) { + + // Parse the subject of the vote + val proposalSubject = try { + JSONObject(proposalBlock.transaction["message"].toString()).get("VOTE_SUBJECT") + } catch (e: JSONException) { + Log.e("vote-debug", "Invalidly formatted proposal block, perhaps not a proposal") + } + // Reply to the vote with YES or NO. val voteReply = if (vote) "YES" else "NO" // Create a JSON object containing the vote subject and the reply. val voteJSON = JSONObject() - .put("VOTE_SUBJECT", voteSubject) + .put("VOTE_SUBJECT", proposalSubject) .put("VOTE_REPLY", voteReply) // Put the JSON string in the transaction's 'message' field. From f7b5be68ccc0842e054285b956b8ff783c4d1505 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 16:25:11 +0200 Subject: [PATCH 12/26] fixed gradle log bug (thanks Matt) --- common/build.gradle | 2 +- .../src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index f8833e671..56edba3b9 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -77,7 +77,7 @@ dependencies { // Logging implementation 'io.github.microutils:kotlin-logging:1.7.7' - implementation 'com.github.tony19:logback-android:2.0.0' + //implementation 'com.github.tony19:logback-android:2.0.0' implementation 'com.mattskala:itemadapter:0.3' diff --git a/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt b/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt index 3eb86bfe1..4d2ade240 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt @@ -11,7 +11,7 @@ import nl.tudelft.trustchain.common.util.TrustChainHelper import nl.tudelft.trustchain.common.util.VotingHelper import java.util.* -open class DemoCommunity : Community() { +class DemoCommunity : Community() { override val serviceId = "02313685c1912a141279f8248fc8db5899c5df5a" val discoveredAddressesContacted: MutableMap = mutableMapOf() From 86b9e1d58611b63f932c9e5fbfba4a7d39a81244 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 18:21:28 +0200 Subject: [PATCH 13/26] fixed gradle bug (thanks Matt again) --- common/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/build.gradle b/common/build.gradle index 56edba3b9..673f5ec0a 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -90,4 +90,6 @@ dependencies { androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.3' testImplementation "io.mockk:mockk:1.9.3" + testImplementation 'org.json:json:20190722' + } From 6495589c764704d581f16b51803bc1cb0bcce25c Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 18:36:44 +0200 Subject: [PATCH 14/26] add validator --- .../nl/tudelft/trustchain/common/util/VotingHelperTest.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index d4140760f..f33c7b583 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -1,5 +1,6 @@ import com.goterl.lazycode.lazysodium.LazySodiumJava import com.goterl.lazycode.lazysodium.SodiumJava +import io.mockk.every import io.mockk.mockk import io.mockk.spyk import io.mockk.verify @@ -12,6 +13,7 @@ import nl.tudelft.ipv8.Peer import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.attestation.trustchain.TrustChainSettings import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore +import nl.tudelft.ipv8.attestation.trustchain.validation.TransactionValidator import nl.tudelft.ipv8.keyvault.JavaCryptoProvider import nl.tudelft.ipv8.keyvault.LibNaClSK import nl.tudelft.ipv8.keyvault.PrivateKey @@ -81,6 +83,10 @@ class VotingHelperTest { val helper = TrustChainHelper(community) val votingHelper = VotingHelper(community) + val validator = mockk() + every { validator.validate(any(), any()) } returns true + community.registerTransactionValidator("voting_block", validator) + // Create list of your peers and include yourself val peers: MutableList = ArrayList() peers.addAll(community.getPeers().map { it.publicKey }) From bc2abc99e244e32810ba302a3515effeb192f556 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 19:47:54 +0200 Subject: [PATCH 15/26] setup for count test --- .../common/util/VotingHelperTest.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index f33c7b583..9385677bc 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.test.TestCoroutineDispatcher import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.setMain import nl.tudelft.ipv8.Peer +import nl.tudelft.ipv8.attestation.trustchain.EMPTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.attestation.trustchain.TrustChainSettings import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore @@ -83,6 +84,7 @@ class VotingHelperTest { val helper = TrustChainHelper(community) val votingHelper = VotingHelper(community) + // Add a validator to the community val validator = mockk() every { validator.validate(any(), any()) } returns true community.registerTransactionValidator("voting_block", validator) @@ -109,5 +111,37 @@ class VotingHelperTest { @Test fun countVotes() { + val community = getCommunity() + val helper = TrustChainHelper(community) + val votingHelper = VotingHelper(community) + + // Add a validator to the community + val validator = mockk() + every { validator.validate(any(), any()) } returns true + community.registerTransactionValidator("voting_block", validator) + + // Create list of your peers and include yourself + val peers: MutableList = ArrayList() + peers.addAll(community.getPeers().map { it.publicKey }) + peers.add(community.myPeer.publicKey) + + val voteSubject = "There should be tests" + + val propBlock = community.createProposalBlock("voting_block", mapOf("message" to voteSubject), EMPTY_PK) + + val voteJSON = JSONObject() + .put("VOTE_SUBJECT", voteSubject) + .put("VOTE_REPLY", "YES") + + // Put the JSON string in the transaction's 'message' field. + val transaction = mapOf("message" to voteJSON.toString()) + + community.createAgreementBlock(propBlock, transaction) + + val count = votingHelper.countVotes(peers, voteSubject, propBlock.publicKey) + + val expectedCount = Pair(0, 1) + + verify { count == expectedCount } } } From 0f09b043db52282e757625031014d1de2ea3ed77 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 20:16:56 +0200 Subject: [PATCH 16/26] improved voting, not quite there yet --- .../common/util/VotingHelperTest.kt | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index 9385677bc..aeb43b892 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -24,14 +24,17 @@ import nl.tudelft.ipv8.peerdiscovery.Network import nl.tudelft.ipv8.util.hexToBytes import nl.tudelft.trustchain.common.util.TrustChainHelper import nl.tudelft.trustchain.common.util.VotingHelper +import org.json.JSONArray import org.json.JSONException import org.json.JSONObject import org.junit.After +import org.junit.Assert import org.junit.Before import org.junit.Test private val lazySodium = LazySodiumJava(SodiumJava()) + class VotingHelperTest { private fun getCommunity(): TrustChainCommunity { @@ -81,6 +84,13 @@ class VotingHelperTest { @Test fun startVote() { val community = getCommunity() + val store = community.database + every { store.getLatest(any(), any()) } returns null + every { store.contains(any()) } returns false + every { store.addBlock(any()) } returns Unit + every { store.getBlockBefore(any()) } returns null + every { store.getBlockAfter(any()) } returns null + val helper = TrustChainHelper(community) val votingHelper = VotingHelper(community) @@ -98,11 +108,11 @@ class VotingHelperTest { votingHelper.startVote(voteSubject, peers) // Verify that the proposal block has been casted - verify { + assert( helper.getChainByUser(community.myPeer.publicKey.keyToBin()).any { JSONObject(it.transaction["message"].toString()).get("VOTE_SUBJECT") == voteSubject } - } + ) } @Test @@ -112,6 +122,13 @@ class VotingHelperTest { @Test fun countVotes() { val community = getCommunity() + val store = community.database + every { store.getLatest(any(), any()) } returns null + every { store.contains(any()) } returns false + every { store.addBlock(any()) } returns Unit + every { store.getBlockBefore(any()) } returns null + every { store.getBlockAfter(any()) } returns null + val helper = TrustChainHelper(community) val votingHelper = VotingHelper(community) @@ -127,8 +144,23 @@ class VotingHelperTest { val voteSubject = "There should be tests" - val propBlock = community.createProposalBlock("voting_block", mapOf("message" to voteSubject), EMPTY_PK) + // Launch proposition + val voteList = JSONArray(peers) + + // Create a JSON object containing the vote subject, as well as a log of the eligible voters + val voteJSONProp = JSONObject() + .put("VOTE_SUBJECT", voteSubject) + .put("VOTE_LIST", voteList) + val transactionProp = voteJSONProp.toString() + val propBlock = community.createProposalBlock( + "voting_block", + mapOf("message" to transactionProp), + EMPTY_PK + ) + + + // Create a reply agreement block val voteJSON = JSONObject() .put("VOTE_SUBJECT", voteSubject) .put("VOTE_REPLY", "YES") @@ -139,9 +171,6 @@ class VotingHelperTest { community.createAgreementBlock(propBlock, transaction) val count = votingHelper.countVotes(peers, voteSubject, propBlock.publicKey) - - val expectedCount = Pair(0, 1) - - verify { count == expectedCount } + Assert.assertEquals(Pair(0, 1), count) } } From 8c875ff06a7c3720267f99d94d675c4425c98af5 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 20:58:18 +0200 Subject: [PATCH 17/26] Add new peers. --- .../common/util/VotingHelperTest.kt | 59 ++++++++----------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index aeb43b892..563c78e2f 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -3,7 +3,6 @@ import com.goterl.lazycode.lazysodium.SodiumJava import io.mockk.every import io.mockk.mockk import io.mockk.spyk -import io.mockk.verify import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestCoroutineDispatcher @@ -15,17 +14,13 @@ import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.attestation.trustchain.TrustChainSettings import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore import nl.tudelft.ipv8.attestation.trustchain.validation.TransactionValidator -import nl.tudelft.ipv8.keyvault.JavaCryptoProvider -import nl.tudelft.ipv8.keyvault.LibNaClSK -import nl.tudelft.ipv8.keyvault.PrivateKey -import nl.tudelft.ipv8.keyvault.PublicKey +import nl.tudelft.ipv8.keyvault.* import nl.tudelft.ipv8.messaging.EndpointAggregator import nl.tudelft.ipv8.peerdiscovery.Network import nl.tudelft.ipv8.util.hexToBytes import nl.tudelft.trustchain.common.util.TrustChainHelper import nl.tudelft.trustchain.common.util.VotingHelper import org.json.JSONArray -import org.json.JSONException import org.json.JSONObject import org.junit.After import org.junit.Assert @@ -84,24 +79,20 @@ class VotingHelperTest { @Test fun startVote() { val community = getCommunity() - val store = community.database - every { store.getLatest(any(), any()) } returns null - every { store.contains(any()) } returns false - every { store.addBlock(any()) } returns Unit - every { store.getBlockBefore(any()) } returns null - every { store.getBlockAfter(any()) } returns null + every { community.database.getLatest(any(), any()) } returns null + every { community.database.contains(any()) } returns false + every { community.database.addBlock(any()) } returns Unit + every { community.database.getBlockBefore(any()) } returns null + every { community.database.getBlockAfter(any()) } returns null val helper = TrustChainHelper(community) val votingHelper = VotingHelper(community) - // Add a validator to the community - val validator = mockk() - every { validator.validate(any(), any()) } returns true - community.registerTransactionValidator("voting_block", validator) - // Create list of your peers and include yourself val peers: MutableList = ArrayList() - peers.addAll(community.getPeers().map { it.publicKey }) + peers.add(defaultCryptoProvider.generateKey().pub()) + peers.add(defaultCryptoProvider.generateKey().pub()) + peers.add(defaultCryptoProvider.generateKey().pub()) peers.add(community.myPeer.publicKey) val voteSubject = "There should be tests" @@ -122,24 +113,19 @@ class VotingHelperTest { @Test fun countVotes() { val community = getCommunity() - val store = community.database - every { store.getLatest(any(), any()) } returns null - every { store.contains(any()) } returns false - every { store.addBlock(any()) } returns Unit - every { store.getBlockBefore(any()) } returns null - every { store.getBlockAfter(any()) } returns null + every { community.database.getLatest(any(), any()) } returns null + every { community.database.contains(any()) } returns false + every { community.database.addBlock(any()) } returns Unit + every { community.database.getBlockBefore(any()) } returns null + every { community.database.getBlockAfter(any()) } returns null - val helper = TrustChainHelper(community) val votingHelper = VotingHelper(community) - // Add a validator to the community - val validator = mockk() - every { validator.validate(any(), any()) } returns true - community.registerTransactionValidator("voting_block", validator) - // Create list of your peers and include yourself val peers: MutableList = ArrayList() - peers.addAll(community.getPeers().map { it.publicKey }) + peers.add(defaultCryptoProvider.generateKey().pub()) + peers.add(defaultCryptoProvider.generateKey().pub()) + peers.add(defaultCryptoProvider.generateKey().pub()) peers.add(community.myPeer.publicKey) val voteSubject = "There should be tests" @@ -158,7 +144,7 @@ class VotingHelperTest { mapOf("message" to transactionProp), EMPTY_PK ) - + community.database.addBlock(propBlock) // Create a reply agreement block val voteJSON = JSONObject() @@ -167,10 +153,15 @@ class VotingHelperTest { // Put the JSON string in the transaction's 'message' field. val transaction = mapOf("message" to voteJSON.toString()) - community.createAgreementBlock(propBlock, transaction) - val count = votingHelper.countVotes(peers, voteSubject, propBlock.publicKey) + val count = + votingHelper.countVotes(peers, voteSubject, community.myPeer.publicKey.keyToBin()) + + // Why does this return 0? + println(community.database.getBlockCount()) + + Assert.assertEquals(Pair(0, 1), count) } } From 7742c3cce7f488f7637dbd896d25b98dbd0c90ce Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Fri, 3 Apr 2020 21:14:26 +0200 Subject: [PATCH 18/26] Removed unused lines --- .../test/java/nl/tudelft/trustchain/common/ExampleUnitTest.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/src/test/java/nl/tudelft/trustchain/common/ExampleUnitTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/ExampleUnitTest.kt index 961cb5ed8..7a4fc2e44 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/ExampleUnitTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/ExampleUnitTest.kt @@ -15,5 +15,3 @@ class ExampleUnitTest { assertEquals(4, 2 + 2) } } - - From fd18c8dcc86f3fe7aad65baff017a0c09126aef0 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Sun, 5 Apr 2020 12:28:09 +0200 Subject: [PATCH 19/26] Improved testing, successfully mocked store --- common/build.gradle | 2 + .../common/util/VotingHelperTest.kt | 114 +++++++++--------- 2 files changed, 61 insertions(+), 55 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 673f5ec0a..b29b737eb 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -91,5 +91,7 @@ dependencies { testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.3' testImplementation "io.mockk:mockk:1.9.3" testImplementation 'org.json:json:20190722' + testImplementation "com.squareup.sqldelight:sqlite-driver:$sqldelight_version" + } diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index 563c78e2f..7a31911e0 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -1,8 +1,11 @@ import com.goterl.lazycode.lazysodium.LazySodiumJava import com.goterl.lazycode.lazysodium.SodiumJava +import com.squareup.sqldelight.db.SqlDriver +import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver import io.mockk.every import io.mockk.mockk import io.mockk.spyk +import io.mockk.verify import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestCoroutineDispatcher @@ -12,11 +15,13 @@ import nl.tudelft.ipv8.Peer import nl.tudelft.ipv8.attestation.trustchain.EMPTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.attestation.trustchain.TrustChainSettings +import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainSQLiteStore import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore import nl.tudelft.ipv8.attestation.trustchain.validation.TransactionValidator import nl.tudelft.ipv8.keyvault.* import nl.tudelft.ipv8.messaging.EndpointAggregator import nl.tudelft.ipv8.peerdiscovery.Network +import nl.tudelft.ipv8.sqldelight.Database import nl.tudelft.ipv8.util.hexToBytes import nl.tudelft.trustchain.common.util.TrustChainHelper import nl.tudelft.trustchain.common.util.VotingHelper @@ -32,35 +37,35 @@ private val lazySodium = LazySodiumJava(SodiumJava()) class VotingHelperTest { + private fun createTrustChainStore(): TrustChainSQLiteStore { + val driver: SqlDriver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY) + Database.Schema.create(driver) + val database = Database(driver) + return TrustChainSQLiteStore(database) + } + + private fun getPeers(): List { + val peers: MutableList = ArrayList() + peers.add(defaultCryptoProvider.generateKey().pub()) + peers.add(defaultCryptoProvider.generateKey().pub()) + peers.add(defaultCryptoProvider.generateKey().pub()) + peers.add(getMyPeer().publicKey) + + return peers + } + private fun getCommunity(): TrustChainCommunity { val settings = TrustChainSettings() - val store = mockk(relaxed = true) + val store = createTrustChainStore() val community = TrustChainCommunity(settings = settings, database = store) community.myPeer = getMyPeer() community.endpoint = getEndpoint() community.network = Network() community.maxPeers = 20 community.cryptoProvider = JavaCryptoProvider - community.load() return community } - @ExperimentalCoroutinesApi - private val testDispatcher = TestCoroutineDispatcher() - - @ExperimentalCoroutinesApi - @Before - fun setUp() { - Dispatchers.setMain(testDispatcher) - } - - @ExperimentalCoroutinesApi - @After - fun tearDown() { - Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher - testDispatcher.cleanupTestCoroutines() - } - protected fun getPrivateKey(): PrivateKey { val privateKey = "81df0af4c88f274d5228abb894a68906f9e04c902a09c68b9278bf2c7597eaf6" val signSeed = "c5c416509d7d262bddfcef421fc5135e0d2bdeb3cb36ae5d0b50321d766f19f2" @@ -78,12 +83,7 @@ class VotingHelperTest { @Test fun startVote() { - val community = getCommunity() - every { community.database.getLatest(any(), any()) } returns null - every { community.database.contains(any()) } returns false - every { community.database.addBlock(any()) } returns Unit - every { community.database.getBlockBefore(any()) } returns null - every { community.database.getBlockAfter(any()) } returns null + val community = spyk(getCommunity()) val helper = TrustChainHelper(community) val votingHelper = VotingHelper(community) @@ -108,17 +108,7 @@ class VotingHelperTest { @Test fun respondToVote() { - } - - @Test - fun countVotes() { - val community = getCommunity() - every { community.database.getLatest(any(), any()) } returns null - every { community.database.contains(any()) } returns false - every { community.database.addBlock(any()) } returns Unit - every { community.database.getBlockBefore(any()) } returns null - every { community.database.getBlockAfter(any()) } returns null - + val community = spyk(getCommunity()) val votingHelper = VotingHelper(community) // Create list of your peers and include yourself @@ -128,40 +118,54 @@ class VotingHelperTest { peers.add(defaultCryptoProvider.generateKey().pub()) peers.add(community.myPeer.publicKey) - val voteSubject = "There should be tests" - // Launch proposition - val voteList = JSONArray(peers) + val voteSubject = "A vote should be counted" + val propBlock = community.createProposalBlock( + "voting_block", + mapOf("message" to voteSubject), + EMPTY_PK + ) + + // Create a reply agreement block + votingHelper.respondToVote(true, propBlock) + + val helper = TrustChainHelper(community) + assert( + helper.getChainByUser(community.myPeer.publicKey.keyToBin()).any { + JSONObject(it.transaction["message"].toString()).get("VOTE_REPLY") == "YES" + } + ) + + } + + @Test + fun countVotes() { + val community = spyk(getCommunity()) + val votingHelper = VotingHelper(community) + val peers = getPeers() - // Create a JSON object containing the vote subject, as well as a log of the eligible voters - val voteJSONProp = JSONObject() - .put("VOTE_SUBJECT", voteSubject) - .put("VOTE_LIST", voteList) - val transactionProp = voteJSONProp.toString() + // Launch proposition + val voteSubject = "A vote should be counted" val propBlock = community.createProposalBlock( "voting_block", - mapOf("message" to transactionProp), + mapOf("message" to voteSubject), EMPTY_PK ) - community.database.addBlock(propBlock) // Create a reply agreement block - val voteJSON = JSONObject() - .put("VOTE_SUBJECT", voteSubject) - .put("VOTE_REPLY", "YES") + votingHelper.respondToVote(true, propBlock) - // Put the JSON string in the transaction's 'message' field. - val transaction = mapOf("message" to voteJSON.toString()) - community.createAgreementBlock(propBlock, transaction) + val helper = TrustChainHelper(community) + helper.getChainByUser(community.myPeer.publicKey.keyToBin()).forEach { + println(JSONObject(it.transaction["message"].toString())) + } val count = votingHelper.countVotes(peers, voteSubject, community.myPeer.publicKey.keyToBin()) - // Why does this return 0? - println(community.database.getBlockCount()) - - Assert.assertEquals(Pair(0, 1), count) } + + } From 89cd8d7430b5aee6eb0202400d015207b0bcc31d Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Sun, 5 Apr 2020 12:42:46 +0200 Subject: [PATCH 20/26] Fixed tests, temp commented out breaking if statement --- .../trustchain/common/util/VotingHelper.kt | 8 +++--- .../common/util/VotingHelperTest.kt | 28 ++++++++++++++----- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index e1448530e..f3c9e57f4 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -141,10 +141,10 @@ class VotingHelper( continue } - // Check whether the voter is in voting list - if (!voters.contains(blockPublicKey)) { - continue - } +// // Check whether the voter is in voting list +// if (!voters.contains(blockPublicKey)) { +// continue +// } // Add the votes, or assume a malicious vote if it is not YES or NO. when (voteJSON.get("VOTE_REPLY")) { diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index 7a31911e0..2d346e1e4 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -120,12 +120,19 @@ class VotingHelperTest { // Launch proposition val voteSubject = "A vote should be counted" + val voteJSON = JSONObject() + .put("VOTE_SUBJECT", voteSubject) + .put("VOTE_LIST", peers) + + val transaction = voteJSON.toString() + val propBlock = community.createProposalBlock( "voting_block", - mapOf("message" to voteSubject), + mapOf("message" to transaction), EMPTY_PK ) + // Create a reply agreement block votingHelper.respondToVote(true, propBlock) @@ -147,24 +154,31 @@ class VotingHelperTest { // Launch proposition val voteSubject = "A vote should be counted" + val voteJSON = JSONObject() + .put("VOTE_SUBJECT", voteSubject) + .put("VOTE_LIST", peers) + + val transaction = voteJSON.toString() + val propBlock = community.createProposalBlock( "voting_block", - mapOf("message" to voteSubject), + mapOf("message" to transaction), EMPTY_PK ) // Create a reply agreement block votingHelper.respondToVote(true, propBlock) - val helper = TrustChainHelper(community) - helper.getChainByUser(community.myPeer.publicKey.keyToBin()).forEach { - println(JSONObject(it.transaction["message"].toString())) - } + // For debugging purposes +// val helper = TrustChainHelper(community) +// helper.getChainByUser(community.myPeer.publicKey.keyToBin()).forEach { +// println(JSONObject(it.transaction["message"].toString())) +// } val count = votingHelper.countVotes(peers, voteSubject, community.myPeer.publicKey.keyToBin()) - Assert.assertEquals(Pair(0, 1), count) + Assert.assertEquals(Pair(1, 0), count) } From 8fa6e850bc94aa09c8f08e471278670cd712fdca Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Sun, 5 Apr 2020 12:45:41 +0200 Subject: [PATCH 21/26] Removed unused imports --- .../trustchain/common/util/VotingHelper.kt | 3 --- .../common/util/VotingHelperTest.kt | 26 +++++-------------- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index f3c9e57f4..1d2921875 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -5,7 +5,6 @@ import nl.tudelft.ipv8.attestation.trustchain.EMPTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.keyvault.PublicKey -import nl.tudelft.ipv8.keyvault.defaultCryptoProvider import org.json.JSONArray import org.json.JSONException import org.json.JSONObject @@ -48,7 +47,6 @@ class VotingHelper( /** * Respond to a proposal block on the trustchain, either agree with "YES" or disagree "NO". - * @param voteSubject the matter to be voted upon. * @param vote boolean value indicating the decision. * @param proposalBlock TrustChainBlock of the proposalblock. */ @@ -97,7 +95,6 @@ class VotingHelper( // Crawl the chain of the proposer. for (it in trustChainHelper.getChainByUser(proposerKey)) { - val blockPublicKey = defaultCryptoProvider.keyFromPublicBin(it.publicKey) // Check whether vote has already been counted if (votes.contains(it.publicKey.contentToString())) { diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index 2d346e1e4..d87ff144c 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -1,41 +1,29 @@ +package nl.tudelft.trustchain.common.util + import com.goterl.lazycode.lazysodium.LazySodiumJava import com.goterl.lazycode.lazysodium.SodiumJava import com.squareup.sqldelight.db.SqlDriver import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver -import io.mockk.every import io.mockk.mockk import io.mockk.spyk -import io.mockk.verify -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestCoroutineDispatcher -import kotlinx.coroutines.test.resetMain -import kotlinx.coroutines.test.setMain import nl.tudelft.ipv8.Peer import nl.tudelft.ipv8.attestation.trustchain.EMPTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.attestation.trustchain.TrustChainSettings import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainSQLiteStore -import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore -import nl.tudelft.ipv8.attestation.trustchain.validation.TransactionValidator import nl.tudelft.ipv8.keyvault.* import nl.tudelft.ipv8.messaging.EndpointAggregator import nl.tudelft.ipv8.peerdiscovery.Network import nl.tudelft.ipv8.sqldelight.Database import nl.tudelft.ipv8.util.hexToBytes -import nl.tudelft.trustchain.common.util.TrustChainHelper -import nl.tudelft.trustchain.common.util.VotingHelper -import org.json.JSONArray import org.json.JSONObject -import org.junit.After import org.junit.Assert -import org.junit.Before import org.junit.Test -private val lazySodium = LazySodiumJava(SodiumJava()) +class VotingHelperTest { -class VotingHelperTest { + private val lazySodium = LazySodiumJava(SodiumJava()) private fun createTrustChainStore(): TrustChainSQLiteStore { val driver: SqlDriver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY) @@ -66,17 +54,17 @@ class VotingHelperTest { return community } - protected fun getPrivateKey(): PrivateKey { + private fun getPrivateKey(): PrivateKey { val privateKey = "81df0af4c88f274d5228abb894a68906f9e04c902a09c68b9278bf2c7597eaf6" val signSeed = "c5c416509d7d262bddfcef421fc5135e0d2bdeb3cb36ae5d0b50321d766f19f2" return LibNaClSK(privateKey.hexToBytes(), signSeed.hexToBytes(), lazySodium) } - protected fun getMyPeer(): Peer { + private fun getMyPeer(): Peer { return Peer(getPrivateKey()) } - protected fun getEndpoint(): EndpointAggregator { + private fun getEndpoint(): EndpointAggregator { return spyk(EndpointAggregator(mockk(relaxed = true), null)) } From ca01e67a0a768969d4ed1959db2c98a7ecb573d6 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Sun, 5 Apr 2020 13:21:22 +0200 Subject: [PATCH 22/26] Fixed checking if voter is eligible to do so. --- .../trustchain/common/util/VotingHelper.kt | 10 ++++---- .../common/util/VotingHelperTest.kt | 24 ++----------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index 1d2921875..cc4a312c9 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -5,6 +5,7 @@ import nl.tudelft.ipv8.attestation.trustchain.EMPTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.keyvault.PublicKey +import nl.tudelft.ipv8.keyvault.defaultCryptoProvider import org.json.JSONArray import org.json.JSONException import org.json.JSONObject @@ -95,6 +96,7 @@ class VotingHelper( // Crawl the chain of the proposer. for (it in trustChainHelper.getChainByUser(proposerKey)) { + val blockPublicKey: PublicKey = defaultCryptoProvider.keyFromPublicBin(it.publicKey) // Check whether vote has already been counted if (votes.contains(it.publicKey.contentToString())) { @@ -138,10 +140,10 @@ class VotingHelper( continue } -// // Check whether the voter is in voting list -// if (!voters.contains(blockPublicKey)) { -// continue -// } + // Check whether the voter is in voting list + if (!voters.any { v -> v.pub().toString() == blockPublicKey.pub().toString() }) { + continue + } // Add the votes, or assume a malicious vote if it is not YES or NO. when (voteJSON.get("VOTE_REPLY")) { diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index d87ff144c..521b6c9ea 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -75,13 +75,7 @@ class VotingHelperTest { val helper = TrustChainHelper(community) val votingHelper = VotingHelper(community) - - // Create list of your peers and include yourself - val peers: MutableList = ArrayList() - peers.add(defaultCryptoProvider.generateKey().pub()) - peers.add(defaultCryptoProvider.generateKey().pub()) - peers.add(defaultCryptoProvider.generateKey().pub()) - peers.add(community.myPeer.publicKey) + val peers = getPeers() val voteSubject = "There should be tests" votingHelper.startVote(voteSubject, peers) @@ -98,13 +92,7 @@ class VotingHelperTest { fun respondToVote() { val community = spyk(getCommunity()) val votingHelper = VotingHelper(community) - - // Create list of your peers and include yourself - val peers: MutableList = ArrayList() - peers.add(defaultCryptoProvider.generateKey().pub()) - peers.add(defaultCryptoProvider.generateKey().pub()) - peers.add(defaultCryptoProvider.generateKey().pub()) - peers.add(community.myPeer.publicKey) + val peers = getPeers() // Launch proposition val voteSubject = "A vote should be counted" @@ -120,7 +108,6 @@ class VotingHelperTest { EMPTY_PK ) - // Create a reply agreement block votingHelper.respondToVote(true, propBlock) @@ -139,7 +126,6 @@ class VotingHelperTest { val votingHelper = VotingHelper(community) val peers = getPeers() - // Launch proposition val voteSubject = "A vote should be counted" val voteJSON = JSONObject() @@ -157,12 +143,6 @@ class VotingHelperTest { // Create a reply agreement block votingHelper.respondToVote(true, propBlock) - // For debugging purposes -// val helper = TrustChainHelper(community) -// helper.getChainByUser(community.myPeer.publicKey.keyToBin()).forEach { -// println(JSONObject(it.transaction["message"].toString())) -// } - val count = votingHelper.countVotes(peers, voteSubject, community.myPeer.publicKey.keyToBin()) From 499c288bb63695ac008664970e0d70990529de91 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Sun, 5 Apr 2020 13:31:33 +0200 Subject: [PATCH 23/26] improved eligible check, required tostring() --- .../java/nl/tudelft/trustchain/common/DemoCommunity.kt | 2 -- .../java/nl/tudelft/trustchain/common/util/VotingHelper.kt | 7 +------ 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt b/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt index 4d2ade240..60a9a0b7f 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/DemoCommunity.kt @@ -2,12 +2,10 @@ package nl.tudelft.trustchain.common import nl.tudelft.ipv8.IPv4Address import nl.tudelft.ipv8.Community -import nl.tudelft.ipv8.IPv8 import nl.tudelft.ipv8.Peer import nl.tudelft.ipv8.android.IPv8Android import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity import nl.tudelft.ipv8.messaging.payload.IntroductionResponsePayload -import nl.tudelft.trustchain.common.util.TrustChainHelper import nl.tudelft.trustchain.common.util.VotingHelper import java.util.* diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index cc4a312c9..694b5c4b8 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -22,7 +22,6 @@ class VotingHelper( private val trustChainHelper: TrustChainHelper = TrustChainHelper(trustChainCommunity) - /** * Initiate a vote amongst a set of peers. * @param voteSubject the matter to be voted upon. @@ -42,10 +41,8 @@ class VotingHelper( // Create any-counterparty block for the transaction trustChainHelper.createProposalBlock(transaction, EMPTY_PK, votingBlock) - } - /** * Respond to a proposal block on the trustchain, either agree with "YES" or disagree "NO". * @param vote boolean value indicating the decision. @@ -74,7 +71,6 @@ class VotingHelper( trustChainHelper.createAgreementBlock(proposalBlock, transaction) } - /** * Return the tally on a vote proposal in a pair(yes, no). * @param voters list of the public keys of the eligible voters. @@ -141,7 +137,7 @@ class VotingHelper( } // Check whether the voter is in voting list - if (!voters.any { v -> v.pub().toString() == blockPublicKey.pub().toString() }) { + if (!voters.any { v -> v.toString().equals(blockPublicKey.toString()) }) { continue } @@ -162,7 +158,6 @@ class VotingHelper( return Pair(yesCount, noCount) } - /** * Helper function for debugging purposes */ From 7053e10f2b980ae706c260e6904e9eb338f3e309 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Sun, 5 Apr 2020 21:28:20 +0200 Subject: [PATCH 24/26] fix some linting warnings --- .../java/nl/tudelft/trustchain/common/util/VotingHelper.kt | 2 ++ .../nl/tudelft/trustchain/common/util/VotingHelperTest.kt | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index 694b5c4b8..9893da268 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -1,5 +1,6 @@ package nl.tudelft.trustchain.common.util +import android.annotation.SuppressLint import android.util.Log import nl.tudelft.ipv8.attestation.trustchain.EMPTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock @@ -137,6 +138,7 @@ class VotingHelper( } // Check whether the voter is in voting list + @SuppressLint if (!voters.any { v -> v.toString().equals(blockPublicKey.toString()) }) { continue } diff --git a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt index 521b6c9ea..eebe99233 100644 --- a/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt +++ b/common/src/test/java/nl/tudelft/trustchain/common/util/VotingHelperTest.kt @@ -22,7 +22,6 @@ import org.junit.Test class VotingHelperTest { - private val lazySodium = LazySodiumJava(SodiumJava()) private fun createTrustChainStore(): TrustChainSQLiteStore { @@ -68,7 +67,6 @@ class VotingHelperTest { return spyk(EndpointAggregator(mockk(relaxed = true), null)) } - @Test fun startVote() { val community = spyk(getCommunity()) @@ -117,7 +115,6 @@ class VotingHelperTest { JSONObject(it.transaction["message"].toString()).get("VOTE_REPLY") == "YES" } ) - } @Test @@ -148,6 +145,4 @@ class VotingHelperTest { Assert.assertEquals(Pair(1, 0), count) } - - } From 181cb2c63f37a81f9296824d5abbab386bde0855 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Sun, 5 Apr 2020 21:48:47 +0200 Subject: [PATCH 25/26] Check on bin array content instead of string match --- .../java/nl/tudelft/trustchain/common/util/VotingHelper.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index 9893da268..5cbb4f7c5 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -139,7 +139,10 @@ class VotingHelper( // Check whether the voter is in voting list @SuppressLint - if (!voters.any { v -> v.toString().equals(blockPublicKey.toString()) }) { + if (!voters.any { v -> + val voteString = v.keyToBin() + voteString.contentEquals(blockPublicKey.keyToBin()) + }) { continue } From a1bdfbab36d8728e9ecdd7b48784c5b8b4471b95 Mon Sep 17 00:00:00 2001 From: EmieldeSmidt Date: Sun, 5 Apr 2020 21:54:52 +0200 Subject: [PATCH 26/26] removed redundant `toString()`` --- .../main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt index 5cbb4f7c5..ad484809d 100644 --- a/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt +++ b/common/src/main/java/nl/tudelft/trustchain/common/util/VotingHelper.kt @@ -114,7 +114,7 @@ class VotingHelper( // proper JSON. handleInvalidVote( "Block was a voting block but did not contain " + - "proper JSON in its message field: ${it.transaction["message"].toString()}." + "proper JSON in its message field: ${it.transaction["message"]}." ) continue }