public void Voted(BlockchainDetails blockchain, string words) { CopyStatus = ""; MagicWords = words; _blockchain = blockchain; Encrypted = blockchain.ShouldEncryptResults; ProceedCommand.RaiseCanExecuteChanged(); }
private async Task ConnectToBlockchain(BlockchainDetails blockchain) { if (MultiChainVm.Connected) { if (MultiChainVm.Model.Name != blockchain.ChainString) { await MultiChainVm.Disconnect(); } else { return; } } await MultiChainVm.Connect(blockchain.Host, blockchain.Port, blockchain.ChainString); }
private async Task ConnectToBlockchain(BlockchainDetails blockchain) { if (MultiChainVm.Connected) { if (MultiChainVm.Model.Name != blockchain.ChainString) { await MultiChainVm.Disconnect(); } else { return; } } await MultiChainVm.Connect(blockchain.Host, blockchain.Port, blockchain.ChainString); // Ensure our questions have been loaded. Connection may be slow await MultiChainVm.Model.WaitUntilBlockchainSynced(3, new Progress <BlockchainSyncProgress>()); }
public BlockchainViewModel(BlockchainDetails model) { _model = model; }
private async Task GetResults(BlockchainDetails blockchain) { // Ensure the blockchain is up to date var progressModel = new Progress <BlockchainSyncProgress>(UpdateProgress); await MultiChainVm.Model.WaitUntilBlockchainSynced(blockchain.Blocks, progressModel); try { // Read the questions from the blockchain _questions = await MultiChainVm.Model.GetQuestions(); var decryptKey = ""; // Blockchain encrypted, so we need the decryption key to read the results if (blockchain.ShouldEncryptResults) { decryptKey = await _voteClient.GetDecryptKey(blockchain.ChainString); } // Get answers from blockchain _answers = await MultiChainVm.Model.GetResults(blockchain.WalletId, decryptKey); // For each question, get its total for each answer var results = _questions.Select(question => { // Setup response dictionary, answer -> num votes var options = question.Answers.ToDictionary(a => a.Answer, a => 0); foreach (var answer in _answers) { foreach (var questionAnswer in answer.Answers.Where(a => a.Question == question.Number)) { // In case we have anything unusual going on if (!options.ContainsKey(questionAnswer.Answer)) { Debug.WriteLine( $"Unexpected answer for question {questionAnswer.Question}: {questionAnswer.Answer}"); continue; } options[questionAnswer.Answer]++; } } return(new { question.Number, question.Question, Results = options }); }).ToList(); var chartVms = results.Select(q => new ChartViewModel(q.Results) { Question = q.Question }).ToList(); Ui(() => { Loading = false; Results.Clear(); Results.AddRange(chartVms); TotalResults = chartVms.Count; CurrentResults = 1; TransitionView.ShowPage(Results.First()); }); } catch (Exception e) { Debug.WriteLine(e); } }
public void SelectVote(BlockchainDetails blockchain) { _currentDetails = blockchain; Connect(); }
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(); } }