From 2d6fdb4e073739bb5f056d2c572494615562d1c0 Mon Sep 17 00:00:00 2001 From: Lucas Vinicius Date: Thu, 17 Oct 2024 20:35:00 -0300 Subject: [PATCH 1/5] Refactored to remove unnecessary attributes from vote --- Counter/VoteCounter.cs | 61 +++++---------------------------------- Counter/VoteEncoding.cs | 33 +-------------------- Counter/VotesCsvReader.cs | 13 +-------- 3 files changed, 9 insertions(+), 98 deletions(-) diff --git a/Counter/VoteCounter.cs b/Counter/VoteCounter.cs index 837d51b..42a51ca 100644 --- a/Counter/VoteCounter.cs +++ b/Counter/VoteCounter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -12,7 +12,7 @@ namespace Counter { public class VoteCounter { - private record Vote(int PoolId, int Slot, byte[] EncodedValue, byte[] CmsSignature, byte[] ServerSignature, int ServerInstanceId, Asn1Vote Value); + private record Vote(byte[] EncodedValue, byte[] CmsSignature, Asn1VoteChoice Value); private class VoteBatch { @@ -30,7 +30,6 @@ public VoteBatch(int index, IEnumerable encryptedVotes) { private const int BatchSize = 1000; - private readonly Dictionary serverPublicKeys = new Dictionary(); private RSA decryptionKey; private WebVaultKeyParameters decryptionKeyParams; private WebVaultClient webVaultClient; @@ -72,21 +71,6 @@ public async Task CountAsync(FileInfo votesCsvFile, in var results = new ElectionResultCollection(); - Console.Write("Reading server keys ..."); - var voteIndex = 0; - using (var votesCsvReader = VotesCsvReader.Open(votesCsvFile)) { - foreach (var voteRecord in votesCsvReader.GetRecords()) { - if (!serverPublicKeys.ContainsKey(voteRecord.ServerInstanceId)) { - serverPublicKeys[voteRecord.ServerInstanceId] = getPublicKey(Util.DecodeHex(voteRecord.ServerPublicKey)); - Console.Write("."); - } - if (++voteIndex % 1000 == 0) { - Console.Write("."); - } - } - } - Console.WriteLine(); - if (decryptionKey != null || decryptionKeyParams != null) { // Decryption key given, check and count votes @@ -185,17 +169,14 @@ private async Task checkAndCountVotesAsync(ChannelReader inQueue, Ele } private Vote decodeVote(VoteCsvRecord csvEntry) { - var poolId = csvEntry.PoolId; - var slot = csvEntry.Slot; var encodedValue = Util.DecodeHex(csvEntry.Value); var cmsSignature = Util.DecodeHex(csvEntry.CmsSignature); - var serverSignature = Util.DecodeHex(csvEntry.ServerSignature); var value = VoteEncoding.Decode(encodedValue); - return new Vote(poolId, slot, encodedValue, cmsSignature, serverSignature, csvEntry.ServerInstanceId, value); + return new Vote(encodedValue, cmsSignature, value); } private async Task decryptChoicesAsync(List votes) { - var ciphers = votes.SelectMany(v => v.Value.Choices.Select(c => c.EncryptedChoice)); + var ciphers = votes.Select(v => v.Value.EncryptedChoice); var plaintexts = decryptionKey != null ? ciphers.Select(c => decryptionKey.Decrypt(c, RSAEncryptionPadding.OaepSHA256)) : await webVaultClient.DecryptBatchAsync(decryptionKeyParams.KeyId, ciphers); @@ -203,14 +184,6 @@ private async Task decryptChoicesAsync(List votes) { } private void checkVote(Vote vote) { - - // Check server signature - var serverSigOk = verifyServerSignature(serverPublicKeys[vote.ServerInstanceId], vote.CmsSignature, vote.ServerSignature) - || serverPublicKeys.Any(pk => verifyServerSignature(pk.Value, vote.CmsSignature, vote.ServerSignature)); - if (!serverSigOk) { - throw new Exception($"Vote on pool {vote.PoolId} slot {vote.Slot} has an invalid server signature"); - } - var cmsInfo = CmsEncoding.Decode(vote.CmsSignature); var expectedMessageDigestValue = HashAlgorithm.Create(cmsInfo.MessageDigest.Algorithm.Name).ComputeHash(vote.EncodedValue); @@ -228,35 +201,15 @@ private void checkVote(Vote vote) { if (!signatureCertificatePublicKey.VerifyHash(cmsInfo.SignedAttributesDigest.Value, cmsInfo.Signature, cmsInfo.SignedAttributesDigest.Algorithm, RSASignaturePadding.Pkcs1)) { throw new Exception("Signature mismatch"); } - - // Check PoolId and Slot integrity - if (vote.PoolId != vote.Value.PoolId || vote.Slot != vote.Value.Slot) { - throw new Exception("Vote address corruption"); - } } - private bool verifyServerSignature(RSA serverPublicKey, byte[] data, byte[] signature) - => serverPublicKey.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); - private void countVote(ElectionResultCollection results, DecryptionTable choiceDecryptions, Vote vote) { - foreach (var choice in vote.Value.Choices) { - var decryptedChoice = Encoding.UTF8.GetString(choiceDecryptions.GetDecryption(choice.EncryptedChoice)); + var decryptedChoice = Encoding.UTF8.GetString(choiceDecryptions.GetDecryption(vote.Value.EncryptedChoice)); results - .GetOrAddElection(choice.ElectionId) - .GetOrAddDistrict(choice.DistrictId) + .GetOrAddElection(vote.Value.ElectionId) + .GetOrAddDistrict(vote.Value.DistrictId) .GetOrAddParty(decryptedChoice) .Increment(); - } } - - #region Helper methods - - private RSA getPublicKey(byte[] encodedPublicKey) { - var rsa = RSA.Create(); - rsa.ImportSubjectPublicKeyInfo(encodedPublicKey, out _); - return rsa; - } - - #endregion } } diff --git a/Counter/VoteEncoding.cs b/Counter/VoteEncoding.cs index 5619971..3ac51c7 100644 --- a/Counter/VoteEncoding.cs +++ b/Counter/VoteEncoding.cs @@ -7,38 +7,7 @@ namespace Counter { public static class VoteEncoding { - public static Asn1Vote Decode(byte[] encoded) => new Asn1Vote(new Asn1InputStream(encoded).ReadObject()); - } - - public class Asn1Vote { - - public Asn1Vote(Asn1Encodable asn1Object) { - var seq = (Asn1Sequence)asn1Object; - Choices = new Asn1VoteChoiceList(seq[0]); - PoolId = ((DerInteger)seq[1]).Value.IntValue; - Slot = ((DerInteger)seq[2]).Value.IntValue; - } - - public Asn1VoteChoiceList Choices { get; } - - public int PoolId { get; } - - public int Slot { get; } - } - - public class Asn1VoteChoiceList : List { - - public Asn1VoteChoiceList(Asn1Encodable asn1Object) : base(decode(asn1Object)) { - } - - private static IEnumerable decode(Asn1Encodable asn1Object) { - var seq = (Asn1Sequence)asn1Object; - var choices = new List(); - foreach (var item in seq) { - choices.Add(new Asn1VoteChoice(item)); - } - return choices; - } + public static Asn1VoteChoice Decode(byte[] encoded) => new Asn1VoteChoice(new Asn1InputStream(encoded).ReadObject()); } public class Asn1VoteChoice { diff --git a/Counter/VotesCsvReader.cs b/Counter/VotesCsvReader.cs index 41e98ca..5debcc4 100644 --- a/Counter/VotesCsvReader.cs +++ b/Counter/VotesCsvReader.cs @@ -1,4 +1,4 @@ -using CsvHelper; +using CsvHelper; using System; using System.Collections.Generic; using System.Globalization; @@ -10,20 +10,9 @@ namespace Counter { public class VoteCsvRecord { - - public int PoolId { get; set; } - - public int Slot { get; set; } - public string Value { get; set; } public string CmsSignature { get; set; } - - public string ServerSignature { get; set; } - - public int ServerInstanceId { get; set; } - - public string ServerPublicKey { get; set; } } public class VotesCsvReader : IDisposable { From ecbb80cbaf4059b3b05038f10acff3ed23cf0683 Mon Sep 17 00:00:00 2001 From: Lucas Vinicius Date: Wed, 30 Oct 2024 17:04:07 -0300 Subject: [PATCH 2/5] Adjusted csv reader configuration --- Counter/VotesCsvReader.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Counter/VotesCsvReader.cs b/Counter/VotesCsvReader.cs index 5debcc4..34070f3 100644 --- a/Counter/VotesCsvReader.cs +++ b/Counter/VotesCsvReader.cs @@ -1,4 +1,5 @@ using CsvHelper; +using CsvHelper.Configuration; using System; using System.Collections.Generic; using System.Globalization; @@ -24,7 +25,13 @@ public class VotesCsvReader : IDisposable { public static VotesCsvReader Open(FileInfo file) { var stream = file.OpenRead(); var streamReader = new StreamReader(stream); - var csvReader = new CsvReader(streamReader, CultureInfo.InvariantCulture /* default in SSMS is exporting with commas regardless of the OS culture */); + var config = new CsvConfiguration(CultureInfo.InvariantCulture /* default in SSMS is exporting with commas regardless of the OS culture */) { + Delimiter = ";", + HasHeaderRecord = true, + IgnoreBlankLines = true, + TrimOptions = TrimOptions.Trim, + }; + var csvReader = new CsvReader(streamReader, config); return new VotesCsvReader(stream, streamReader, csvReader); } From 6bde5e0e8f5e3df74ba93ec4d6ec6602bda41ff3 Mon Sep 17 00:00:00 2001 From: Lucas Vinicius Date: Thu, 31 Oct 2024 09:58:12 -0300 Subject: [PATCH 3/5] Removed district details from results csv --- Counter/ResultsCsvWriter.cs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/Counter/ResultsCsvWriter.cs b/Counter/ResultsCsvWriter.cs index 6f19f28..efeaed1 100644 --- a/Counter/ResultsCsvWriter.cs +++ b/Counter/ResultsCsvWriter.cs @@ -1,4 +1,4 @@ -using CsvHelper; +using CsvHelper; using CsvHelper.Configuration; using System; using System.Collections.Generic; @@ -17,10 +17,6 @@ public class ResultCsvRecord { public string ElectionLabel { get; set; } - public string DistrictId { get; set; } - - public string DistrictLabel { get; set; } - public string PartyIdentifier { get; set; } public string PartyLabel { get; set; } @@ -54,7 +50,6 @@ public void Write(ElectionResultCollection results, Stream outStream) { var orderedRecords = records .OrderBy(r => r.ElectionLabel) - .ThenBy(r => r.DistrictLabel) .ThenBy(r => r.PartyLabel == BlankVotesLabel || r.PartyLabel == NullVotesLabel ? 1 : 0) .ThenByDescending(r => r.Votes); @@ -86,8 +81,6 @@ private IEnumerable getDistrictRecords(string electionId, strin yield return new ResultCsvRecord { ElectionId = electionId, ElectionLabel = electionLabel, - DistrictId = districtResult.Id, - DistrictLabel = districtLabel, PartyIdentifier = partyResult.Identifier, PartyLabel = getPartyLabel(partyResult), Votes = partyResult.Votes + (partyResult.IsNull ? nullifiedPartyResults.Sum(npr => npr.Votes) : 0), @@ -102,8 +95,6 @@ private IEnumerable getDistrictRecords(string electionId, strin yield return new ResultCsvRecord { ElectionId = electionId, ElectionLabel = electionLabel, - DistrictId = districtResult.Id, - DistrictLabel = districtLabel, PartyIdentifier = party.PartyId, PartyLabel = getPartyLabel(party), Votes = 0, @@ -118,8 +109,6 @@ private IEnumerable getDistrictRecords(string electionId, strin yield return new ResultCsvRecord { ElectionId = electionId, ElectionLabel = electionLabel, - DistrictId = districtResult.Id, - DistrictLabel = districtLabel, PartyIdentifier = PartyResult.BlankIdentifier, PartyLabel = BlankVotesLabel, Votes = 0, @@ -132,8 +121,6 @@ private IEnumerable getDistrictRecords(string electionId, strin yield return new ResultCsvRecord { ElectionId = electionId, ElectionLabel = electionLabel, - DistrictId = districtResult.Id, - DistrictLabel = districtLabel, PartyIdentifier = PartyResult.NullIdentifier, PartyLabel = NullVotesLabel, Votes = nullifiedPartyResults.Sum(npr => npr.Votes), From 094408da2f37603f7fa804cbf092988690e338a0 Mon Sep 17 00:00:00 2001 From: Lucas Vinicius Date: Thu, 31 Oct 2024 17:05:05 -0300 Subject: [PATCH 4/5] Refactored to get the same csv configuration --- Counter/DistrictsCsvReader.cs | 7 +------ Counter/PartiesCsvReader.cs | 7 +------ Counter/ResultsCsvWriter.cs | 8 +------- Counter/Util.cs | 11 ++++++++++- Counter/VotesCsvReader.cs | 13 +------------ 5 files changed, 14 insertions(+), 32 deletions(-) diff --git a/Counter/DistrictsCsvReader.cs b/Counter/DistrictsCsvReader.cs index cbd4cef..d061ef4 100644 --- a/Counter/DistrictsCsvReader.cs +++ b/Counter/DistrictsCsvReader.cs @@ -1,12 +1,7 @@ using CsvHelper; -using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; namespace Counter { @@ -26,7 +21,7 @@ public static class DistrictsCsvReader { public static List Read(FileInfo file) { using var stream = file.OpenRead(); using var streamReader = new StreamReader(stream); - using var csvReader = new CsvReader(streamReader, Thread.CurrentThread.CurrentCulture); + using var csvReader = new CsvReader(streamReader, Util.CsvConfiguration); return csvReader.GetRecords().ToList(); } } diff --git a/Counter/PartiesCsvReader.cs b/Counter/PartiesCsvReader.cs index b06263e..4f4cdab 100644 --- a/Counter/PartiesCsvReader.cs +++ b/Counter/PartiesCsvReader.cs @@ -1,12 +1,7 @@ using CsvHelper; -using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; namespace Counter { @@ -36,7 +31,7 @@ public static class PartiesCsvReader { public static List Read(FileInfo file) { using var stream = file.OpenRead(); using var streamReader = new StreamReader(stream); - using var csvReader = new CsvReader(streamReader, Thread.CurrentThread.CurrentCulture); + using var csvReader = new CsvReader(streamReader, Util.CsvConfiguration); return csvReader.GetRecords().ToList(); } } diff --git a/Counter/ResultsCsvWriter.cs b/Counter/ResultsCsvWriter.cs index efeaed1..cf687b7 100644 --- a/Counter/ResultsCsvWriter.cs +++ b/Counter/ResultsCsvWriter.cs @@ -1,5 +1,4 @@ using CsvHelper; -using CsvHelper.Configuration; using System; using System.Collections.Generic; using System.Globalization; @@ -54,13 +53,11 @@ public void Write(ElectionResultCollection results, Stream outStream) { .ThenByDescending(r => r.Votes); using var streamWriter = new StreamWriter(outStream, Encoding.UTF8); - using var csvWriter = new CsvWriter(streamWriter, Thread.CurrentThread.CurrentCulture); + using var csvWriter = new CsvWriter(streamWriter, Util.CsvConfiguration); csvWriter.WriteRecords(orderedRecords); } private IEnumerable getDistrictRecords(string electionId, string electionLabel, DistrictResult districtResult) { - - var districtLabel = getDistrictLabel(districtResult); // Check which parties need to be nullified @@ -133,9 +130,6 @@ private string getElectionLabel(ElectionResult electionResult) { return partyFromElection != null ? $"{partyFromElection.SubscriptionName} - {partyFromElection.ElectionName}" : null; } - private string getDistrictLabel(DistrictResult districtResult) - => districts?.FirstOrDefault(d => d.DistrictId.Equals(districtResult.Id, StringComparison.OrdinalIgnoreCase))?.DistrictName ?? "(não especificado)"; - private string getPartyLabel(PartyResult partyResult) { if (partyResult.Identifier == PartyResult.BlankIdentifier) { diff --git a/Counter/Util.cs b/Counter/Util.cs index 3200e46..55f5aaf 100644 --- a/Counter/Util.cs +++ b/Counter/Util.cs @@ -1,7 +1,9 @@ -using System; +using CsvHelper.Configuration; +using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace Counter { @@ -29,5 +31,12 @@ public static byte[] DecodePem(string pem) { var base64 = string.Join("", lines.Where(l => !l.StartsWith("---"))); return Convert.FromBase64String(base64); } + + public static CsvConfiguration CsvConfiguration => new CsvConfiguration(Thread.CurrentThread.CurrentCulture) { + Delimiter = ";", + HasHeaderRecord = true, + IgnoreBlankLines = true, + TrimOptions = TrimOptions.Trim, + }; } } diff --git a/Counter/VotesCsvReader.cs b/Counter/VotesCsvReader.cs index 34070f3..2840830 100644 --- a/Counter/VotesCsvReader.cs +++ b/Counter/VotesCsvReader.cs @@ -1,12 +1,7 @@ using CsvHelper; -using CsvHelper.Configuration; using System; using System.Collections.Generic; -using System.Globalization; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Counter { @@ -25,13 +20,7 @@ public class VotesCsvReader : IDisposable { public static VotesCsvReader Open(FileInfo file) { var stream = file.OpenRead(); var streamReader = new StreamReader(stream); - var config = new CsvConfiguration(CultureInfo.InvariantCulture /* default in SSMS is exporting with commas regardless of the OS culture */) { - Delimiter = ";", - HasHeaderRecord = true, - IgnoreBlankLines = true, - TrimOptions = TrimOptions.Trim, - }; - var csvReader = new CsvReader(streamReader, config); + var csvReader = new CsvReader(streamReader, Util.CsvConfiguration); return new VotesCsvReader(stream, streamReader, csvReader); } From d6a438a05570da76ee79a018414748205a2adb09 Mon Sep 17 00:00:00 2001 From: Lucas Vinicius Date: Mon, 4 Nov 2024 16:24:55 -0300 Subject: [PATCH 5/5] Removed all references to districts --- Counter/DistrictsCsvReader.cs | 28 ---------------------------- Counter/Program.cs | 9 +++------ Counter/Results.cs | 19 +------------------ Counter/ResultsCsvWriter.cs | 22 +++++++++------------- Counter/VoteCounter.cs | 1 - Counter/VoteEncoding.cs | 8 ++------ 6 files changed, 15 insertions(+), 72 deletions(-) delete mode 100644 Counter/DistrictsCsvReader.cs diff --git a/Counter/DistrictsCsvReader.cs b/Counter/DistrictsCsvReader.cs deleted file mode 100644 index d061ef4..0000000 --- a/Counter/DistrictsCsvReader.cs +++ /dev/null @@ -1,28 +0,0 @@ -using CsvHelper; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Counter { - - public class DistrictCsvRecord { - - public string SubscriptionId { get; set; } - - public string SubscriptionName { get; set; } - - public string DistrictId { get; set; } - - public string DistrictName { get; set; } - } - - public static class DistrictsCsvReader { - - public static List Read(FileInfo file) { - using var stream = file.OpenRead(); - using var streamReader = new StreamReader(stream); - using var csvReader = new CsvReader(streamReader, Util.CsvConfiguration); - return csvReader.GetRecords().ToList(); - } - } -} diff --git a/Counter/Program.cs b/Counter/Program.cs index 5bcf616..b9f9c20 100644 --- a/Counter/Program.cs +++ b/Counter/Program.cs @@ -20,10 +20,9 @@ async static Task runAsync(string[] args) { var votesCsvPath = args.ElementAtOrDefault(1); var decKeyPath = args.ElementAtOrDefault(2); var partiesCsvPath = args.ElementAtOrDefault(3); - var districtsCsvPath = args.ElementAtOrDefault(4); if (string.IsNullOrEmpty(sigCertPath) || string.IsNullOrEmpty(votesCsvPath)) { - Console.WriteLine("Syntax: Counter [] [] []"); + Console.WriteLine("Syntax: Counter [] []"); return; } @@ -31,11 +30,9 @@ async static Task runAsync(string[] args) { var votesCsvFile = checkPath(votesCsvPath); var decryptionKeyFile = !string.IsNullOrEmpty(decKeyPath) ? checkPath(decKeyPath) : null; var partiesCsvFile = !string.IsNullOrEmpty(partiesCsvPath) ? checkPath(partiesCsvPath) : null; - var districtsCsvFile = !string.IsNullOrEmpty(districtsCsvPath) ? checkPath(districtsCsvPath) : null; - // Parties and districts are only needed later, but we'll read them ahead of time to raise exceptions sooner rather than later + // Parties are only needed later, but we'll read them ahead of time to raise exceptions sooner rather than later var parties = partiesCsvFile != null ? PartiesCsvReader.Read(partiesCsvFile) : null; - var districts = districtsCsvFile != null ? DistrictsCsvReader.Read(districtsCsvFile) : null; var degreeOfParallelismVar = Environment.GetEnvironmentVariable("COUNTER_WORKERS"); var degreeOfParallelism = !string.IsNullOrEmpty(degreeOfParallelismVar) ? int.Parse(degreeOfParallelismVar) : 32; @@ -51,7 +48,7 @@ async static Task runAsync(string[] args) { return; } - var resultsWriter = new ResultsCsvWriter(parties, districts); + var resultsWriter = new ResultsCsvWriter(parties); byte[] resultsFileBytes; using (var buffer = new MemoryStream()) { resultsWriter.Write(results, buffer); diff --git a/Counter/Results.cs b/Counter/Results.cs index b5da048..e5630bd 100644 --- a/Counter/Results.cs +++ b/Counter/Results.cs @@ -19,28 +19,11 @@ public ElectionResult GetOrAddElection(string electionId) public class ElectionResult { - private readonly ConcurrentDictionary districtResults; - - public string Id { get; } - - public ElectionResult(string id) { - Id = id; - districtResults = new ConcurrentDictionary(StringComparer.InvariantCultureIgnoreCase); - } - - public DistrictResult GetOrAddDistrict(string id) - => districtResults.GetOrAdd(id ?? "", new DistrictResult(id)); - - public IEnumerable DistrictResults => districtResults.Values; - } - - public class DistrictResult { - private readonly ConcurrentDictionary partyResults; public string Id { get; } - public DistrictResult(string id) { + public ElectionResult(string id) { Id = id; partyResults = new ConcurrentDictionary(StringComparer.InvariantCultureIgnoreCase); } diff --git a/Counter/ResultsCsvWriter.cs b/Counter/ResultsCsvWriter.cs index cf687b7..d0c7825 100644 --- a/Counter/ResultsCsvWriter.cs +++ b/Counter/ResultsCsvWriter.cs @@ -29,11 +29,9 @@ public class ResultsCsvWriter { private const string NullVotesLabel = "Votos nulos"; private readonly List parties; - private readonly List districts; - public ResultsCsvWriter(List parties, List districts) { + public ResultsCsvWriter(List parties) { this.parties = parties; - this.districts = districts; } public void Write(ElectionResultCollection results, Stream outStream) { @@ -42,9 +40,7 @@ public void Write(ElectionResultCollection results, Stream outStream) { foreach (var electionResult in results.ElectionResults) { var electionLabel = getElectionLabel(electionResult); - foreach (var districtResult in electionResult.DistrictResults) { - records.AddRange(getDistrictRecords(electionResult.Id, electionLabel, districtResult)); - } + records.AddRange(getPartyRecords(electionResult.Id, electionLabel, electionResult.PartyResults)); } var orderedRecords = records @@ -57,13 +53,13 @@ public void Write(ElectionResultCollection results, Stream outStream) { csvWriter.WriteRecords(orderedRecords); } - private IEnumerable getDistrictRecords(string electionId, string electionLabel, DistrictResult districtResult) { + private IEnumerable getPartyRecords(string electionId, string electionLabel, IEnumerable partyResults) { // Check which parties need to be nullified var nullifiedPartyResults = new List(); - foreach (var partyResult in districtResult.PartyResults) { + foreach (var partyResult in partyResults) { if (!partyResult.IsBlankOrNull) { var party = parties?.FirstOrDefault(p => p.PartyId.Equals(partyResult.Identifier, StringComparison.OrdinalIgnoreCase)); if (party != null && !party.IsEnabled) { @@ -74,7 +70,7 @@ private IEnumerable getDistrictRecords(string electionId, strin // Yield parties/blanks/nulls (except nullified ones) - foreach (var partyResult in districtResult.PartyResults.Except(nullifiedPartyResults)) { + foreach (var partyResult in partyResults.Except(nullifiedPartyResults)) { yield return new ResultCsvRecord { ElectionId = electionId, ElectionLabel = electionLabel, @@ -84,11 +80,11 @@ private IEnumerable getDistrictRecords(string electionId, strin }; } - // Yield enabled parties without votes (not in `districtResult.PartyResults`) + // Yield enabled parties without votes (not in `partyResults`) if (parties != null) { foreach (var party in parties.Where(p => p.IsEnabled && p.ElectionId.Equals(electionId, StringComparison.OrdinalIgnoreCase))) { - if (!districtResult.PartyResults.Any(r => r.Identifier.Equals(party.PartyId, StringComparison.OrdinalIgnoreCase))) { + if (!partyResults.Any(r => r.Identifier.Equals(party.PartyId, StringComparison.OrdinalIgnoreCase))) { yield return new ResultCsvRecord { ElectionId = electionId, ElectionLabel = electionLabel, @@ -102,7 +98,7 @@ private IEnumerable getDistrictRecords(string electionId, strin // Yield blanks row if not already yielded - if (!districtResult.PartyResults.Any(p => p.Identifier.Equals(PartyResult.BlankIdentifier, StringComparison.OrdinalIgnoreCase))) { + if (!partyResults.Any(p => p.Identifier.Equals(PartyResult.BlankIdentifier, StringComparison.OrdinalIgnoreCase))) { yield return new ResultCsvRecord { ElectionId = electionId, ElectionLabel = electionLabel, @@ -114,7 +110,7 @@ private IEnumerable getDistrictRecords(string electionId, strin // Yield nulls row if not already yielded - if (!districtResult.PartyResults.Any(p => p.Identifier.Equals(PartyResult.NullIdentifier, StringComparison.OrdinalIgnoreCase))) { + if (!partyResults.Any(p => p.Identifier.Equals(PartyResult.NullIdentifier, StringComparison.OrdinalIgnoreCase))) { yield return new ResultCsvRecord { ElectionId = electionId, ElectionLabel = electionLabel, diff --git a/Counter/VoteCounter.cs b/Counter/VoteCounter.cs index 42a51ca..2babe6f 100644 --- a/Counter/VoteCounter.cs +++ b/Counter/VoteCounter.cs @@ -207,7 +207,6 @@ private void countVote(ElectionResultCollection results, DecryptionTable choiceD var decryptedChoice = Encoding.UTF8.GetString(choiceDecryptions.GetDecryption(vote.Value.EncryptedChoice)); results .GetOrAddElection(vote.Value.ElectionId) - .GetOrAddDistrict(vote.Value.DistrictId) .GetOrAddParty(decryptedChoice) .Increment(); } diff --git a/Counter/VoteEncoding.cs b/Counter/VoteEncoding.cs index 3ac51c7..0f848a6 100644 --- a/Counter/VoteEncoding.cs +++ b/Counter/VoteEncoding.cs @@ -11,18 +11,14 @@ public static class VoteEncoding { } public class Asn1VoteChoice { - - public string ElectionId { get; } - - public string DistrictId { get; } + public string ElectionId{ get; } public byte[] EncryptedChoice { get; } public Asn1VoteChoice(Asn1Encodable asn1Object) { var seq = (Asn1Sequence)asn1Object; ElectionId = ((DerPrintableString)seq[0]).GetString(); - DistrictId = ((DerPrintableString)seq[1]).GetString(); - EncryptedChoice = ((DerOctetString)seq[2]).GetOctets(); + EncryptedChoice = ((DerOctetString)seq[1]).GetOctets(); } } }