public HttpResponseMessage ReferendumLookup(HttpRequestMessage requestMessage, int id) { // Lookup the referendum and 404 it if we cannot find it, otherwise return it as-is using (ReferendumRepository repo = new ReferendumRepository()) { Referendum referendum = repo.Get(id); if (referendum == null) { return(requestMessage.CreateResponse(HttpStatusCode.NotFound)); } return(requestMessage.CreateResponse(HttpStatusCode.OK, referendum)); } }
public HttpResponseMessage ReferendumSummary(HttpRequestMessage requestMessage) { using (ReferendumRepository repo = new ReferendumRepository()) { Referendum[] referendums = repo.GetAll(); if (referendums != null) { foreach (Referendum referendum in referendums) { referendum.StripVoters(); } } return(requestMessage.CreateResponse(HttpStatusCode.OK, referendums)); } }
public HttpResponseMessage ReferendumVote(HttpRequestMessage requestMessage, int id, VoteRequest request) { // Find the referendum that matches using (ReferendumRepository repo = new ReferendumRepository()) { Referendum referendum = repo.Get(id); if (referendum == null) { return(requestMessage.CreateResponse(HttpStatusCode.NotFound)); } // First perform the same checks that the client performs - required fields are provided, the Ethereum address is valid and in our voting list List <string> invalidFields = new List <string>(); List <string> errorMessages = new List <string>(); if (string.IsNullOrEmpty(request?.Address)) { invalidFields.Add("voteAddress"); errorMessages.Add("Your Ethereum address is required"); } else if (request.Address.Length != 42) { invalidFields.Add("voteAddress"); errorMessages.Add("Your Ethereum address is not valid"); } else { bool found = false; foreach (Voter voter in referendum.Electorate) { if (voter.Address.ToLower() != request.Address.ToLower()) { continue; } if (voter.VoteCount == 0) { continue; } found = true; break; } if (!found) { invalidFields.Add("voteAddress"); errorMessages.Add("Your Ethereum address is not entitled to vote"); } } if (request.Vote < 1) { invalidFields.Add("voteAnswer"); errorMessages.Add("Your need to select your voting intention"); } else if (request.Vote > referendum.Answers.Length) { invalidFields.Add("voteAnswer"); errorMessages.Add("Your vote is not valid for this referendum"); } if (string.IsNullOrEmpty(request.SignedVoteMessage)) { invalidFields.Add("signature"); errorMessages.Add("Your need to sign your vote"); } else if (request.SignedVoteMessage.Length != 132) { invalidFields.Add("signature"); errorMessages.Add("Your signature's hex string is not the correct length"); } // Now confirm that the signature is that which we expect, if not generate an error if (!invalidFields.Contains("signature")) { try { MessageSigner signer = new MessageSigner(); string message = "R" + id + " V" + request.Vote + " " + request.Address.ToLower(); string v1Address = signer.EcRecover(new Nethereum.Util.Sha3Keccack().CalculateHash(Encoding.UTF8.GetBytes(message)), request.SignedVoteMessage); string v2Address = signer.EcRecover(new Nethereum.Util.Sha3Keccack().CalculateHash(Encoding.UTF8.GetBytes("\u0019Ethereum Signed Message:\n" + message.Length + message)), request.SignedVoteMessage); string trezorAddress = signer.EcRecover(new Nethereum.Util.Sha3Keccack().CalculateHash(Encoding.UTF8.GetBytes("\u0019Ethereum Signed Message:\n" + char.ConvertFromUtf32(message.Length) + message)), request.SignedVoteMessage); if (v1Address.ToLower() != request.Address.ToLower() && v2Address.ToLower() != request.Address.ToLower() && trezorAddress.ToLower() != request.Address.ToLower()) { invalidFields.Add("signature"); errorMessages.Add("Your signature is not correct"); } } catch (Exception ex) { invalidFields.Add("signature"); errorMessages.Add("Unexpected error decoding your signature: " + ex.Message); } } // Check timings for the vote if (DateTime.UtcNow < referendum.StartTime) { invalidFields.Add(string.Empty); errorMessages.Add("The vote has not yet started"); } if (DateTime.UtcNow > referendum.EndTime) { invalidFields.Add(string.Empty); errorMessages.Add("The vote has already ended"); } // If any errors are present, return them now. if (errorMessages.Count > 0) { return(requestMessage.CreateResponse(HttpStatusCode.BadRequest, new ValidationResponse(invalidFields.ToArray(), errorMessages.ToArray()))); } // Add or update the vote in the backend repo repo.Vote(id, request.Address, request.Vote, request.SignedVoteMessage); // Confirm this to the user return(requestMessage.CreateResponse(HttpStatusCode.NoContent)); } }