private string FormatAnswer(BlockchainVoteModelPlainText answers) { var answerText = ""; foreach (var q in _questions) { if (answerText != "") { answerText += "\n"; } answerText += $"Question: {q.Question}\n"; var answer = answers.Answers.FirstOrDefault(a => a.Question == q.Number); if (answer == null) { answerText += "Answer Not Found!"; } else { answerText += "Answer: " + answer.Answer; } } return(answerText); }
public async Task <string> Vote(List <QuestionViewModel> questions, BlockchainDetails blockchain, IProgress <int> progress) { var voteClient = new VoteClient(); progress.Report(1); try { // Create our random voting token var token = GenerateRandomToken(); // Get the registrar's public key, to use for the blind signature var keyStr = await voteClient.GetPublicKey(Model.Name); var key = RsaTools.PublicKeyFromString(keyStr); // Blind our token progress.Report(2); var blindedToken = RsaTools.BlindMessage(token, key); // Get the token signed by the registrar var blindSignature = await voteClient.GetBlindSignature(Model.Name, blindedToken.Blinded.ToString()); // Unblind the token var unblindedToken = RsaTools.UnblindMessage(new BigInteger(blindSignature), blindedToken.Random, key); // Here we would normally sleep until a random number of other voters have had tokens blindly signed by the registrar. // This would be possible through observation of the root stream using the voters key, or a maximum timeout. // However, given that this is a prototype, there is not enough traffic to make this feasible. progress.Report(3); // Create a wallet address to vote from var walletId = await Model.GetNewWalletAddress(); // Request a voting asset (currency) progress.Report(4); var regiMeta = await voteClient.GetVote(Model.Name, walletId, token, unblindedToken.ToString()); // Wait until the currency has been confirmed progress.Report(5); await Model.ConfirmVoteAllocated(); // Where the transaction's currency comes from progress.Report(6); var txIds = new List <CreateRawTransactionTxIn> { new CreateRawTransactionTxIn { TxId = regiMeta.TxId, Vout = 0 } }; // Where the transaction's currency goes to (registrar) var toInfo = new List <CreateRawTransactionAmount> { new CreateRawTransactionAsset { Address = regiMeta.RegistrarAddress, Qty = 1, Name = MultiChainTools.VOTE_ASSET_NAME } }; // Create our list of answers var answers = questions.Select(q => new BlockchainVoteAnswerModel { Answer = q.SelectedAnswer.Answer, Question = q.QuestionNumber }).ToList(); // Send our vote, encrytped if required if (blockchain.ShouldEncryptResults) { var encryptKey = RsaTools.PublicKeyFromString(blockchain.EncryptKey); var encryptedAnswers = new BlockchainVoteModelEncrypted { MagicWords = regiMeta.Words, Answers = RsaTools.EncryptMessage(JsonConvert.SerializeObject(answers), encryptKey) }; await Model.WriteTransaction(txIds, toInfo, encryptedAnswers); } else { // Send vote in plaintext (live readable results) var answerModel = new BlockchainVoteModelPlainText { MagicWords = regiMeta.Words, Answers = answers }; await Model.WriteTransaction(txIds, toInfo, answerModel); } return(regiMeta.Words); } catch (ApiException) { progress.Report(-1); throw new CouldNotVoteException(); } catch (Exception e) { progress.Report(-1); Debug.WriteLine(e.Message); throw new CouldNotVoteException(); } }