Ejemplo n.º 1
0
        /// <summary>
        /// Execute the Vote action,save the VoteRecords and update the VotingResults and the VotedItems
        /// Before Voting,the VotingItem's token must be locked,except the votes delegated to a contract.
        /// </summary>
        /// <param name="input">VoteInput</param>
        /// <returns></returns>
        public override Empty Vote(VoteInput input)
        {
            var votingItem = AssertValidVoteInput(input);

            var votingRecord = new VotingRecord
            {
                VotingItemId   = input.VotingItemId,
                Amount         = input.Amount,
                SnapshotNumber = votingItem.CurrentSnapshotNumber,
                Option         = input.Option,
                IsWithdrawn    = false,
                VoteTimestamp  = Context.CurrentBlockTime,
                Voter          = input.Voter,
                IsChangeTarget = input.IsChangeTarget
            };

            //save the VotingRecords into the state.
            State.VotingRecords[input.VoteId] = votingRecord;

            UpdateVotingResult(votingItem, input.Option, input.Amount);
            UpdateVotedItems(input.VoteId, votingRecord.Voter, votingItem);

            if (votingItem.IsLockToken)
            {
                // Lock voted token.
                State.TokenContract.Lock.Send(new LockInput
                {
                    Address = votingRecord.Voter,
                    Symbol  = votingItem.AcceptedCurrency,
                    LockId  = input.VoteId,
                    Amount  = input.Amount,
                    Usage   = $"Voting for {input.VotingItemId}"
                });
            }

            Context.Fire(new Voted
            {
                VoteId         = input.VoteId,
                VotingItemId   = votingRecord.VotingItemId,
                Voter          = votingRecord.Voter,
                Amount         = votingRecord.Amount,
                Option         = votingRecord.Option,
                SnapshotNumber = votingRecord.SnapshotNumber,
                VoteTimestamp  = votingRecord.VoteTimestamp
            });

            return(new Empty());
        }
Ejemplo n.º 2
0
        private ElectionVotingRecord TransferVotingRecordToElectionVotingRecord(VotingRecord votingRecord, Hash voteId)
        {
            var lockSeconds = State.LockTimeMap[voteId];

            return(new ElectionVotingRecord
            {
                Voter = votingRecord.Voter,
                Candidate = votingRecord.Option,
                Amount = votingRecord.Amount,
                TermNumber = votingRecord.SnapshotNumber,
                VoteId = voteId,
                LockTime = lockSeconds,
                VoteTimestamp = votingRecord.VoteTimestamp,
                WithdrawTimestamp = votingRecord.WithdrawTimestamp,
                UnlockTimestamp = votingRecord.VoteTimestamp.AddSeconds(lockSeconds),
                IsWithdrawn = votingRecord.IsWithdrawn,
                Weight = GetVotesWeight(votingRecord.Amount, lockSeconds)
            });
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Execute the Vote action,save the VoteRecords and update the VotingResults and the VotedItems
        /// Before Voting,the VotingItem's token must be locked,except the votes delegated to a contract.
        /// </summary>
        /// <param name="input">VoteInput</param>
        /// <returns></returns>
        public override Empty Vote(VoteInput input)
        {
            //the VotingItem is exist in state.
            var votingItem = AssertVotingItem(input.VotingItemId);

            Assert(votingItem.Options.Contains(input.Option), $"Option {input.Option} not found.");
            Assert(votingItem.CurrentSnapshotNumber <= votingItem.TotalSnapshotNumber,
                   "Current voting item already ended.");
            if (!votingItem.IsLockToken)
            {
                Assert(votingItem.Sponsor == Context.Sender, "Sender of delegated voting event must be the Sponsor.");
                Assert(input.Voter != null, "Voter cannot be null if voting event is delegated.");
                Assert(input.VoteId != null, "Vote Id cannot be null if voting event is delegated.");
            }
            else
            {
                //Voter just is the transaction sponsor
                input.Voter = Context.Sender;
                //VoteId just is the transaction ID;
                input.VoteId = Context.TransactionId;
            }

            var votingRecord = new VotingRecord
            {
                VotingItemId   = input.VotingItemId,
                Amount         = input.Amount,
                SnapshotNumber = votingItem.CurrentSnapshotNumber,
                Option         = input.Option,
                IsWithdrawn    = false,
                VoteTimestamp  = Context.CurrentBlockTime,
                Voter          = input.Voter
            };

            //save the VotingRecords into the state.
            State.VotingRecords[input.VoteId] = votingRecord;

            UpdateVotingResult(votingItem, input.Option, input.Amount);
            UpdateVotedItems(input.VoteId, votingRecord.Voter, votingItem);

            if (votingItem.IsLockToken)
            {
                // Lock voted token.
                State.TokenContract.Lock.Send(new LockInput
                {
                    Address = votingRecord.Voter,
                    Symbol  = votingItem.AcceptedCurrency,
                    LockId  = input.VoteId,
                    Amount  = input.Amount,
                    Usage   = $"Voting for {input.VotingItemId}"
                });
            }

            Context.Fire(new Voted
            {
                VoteId         = input.VoteId,
                VotingItemId   = votingRecord.VotingItemId,
                Voter          = votingRecord.Voter,
                Amount         = votingRecord.Amount,
                Option         = votingRecord.Option,
                SnapshotNumber = votingRecord.SnapshotNumber,
                VoteTimestamp  = votingRecord.VoteTimestamp
            });

            return(new Empty());
        }
        private async Task <bool> ProcessRecord(VotingRecord record)
        {
            try
            {
                _logger.LogDebug($"Processing voting record {record.Sequence} for user {record?.Vote?.UserId} on poll {record?.Vote?.PollId}");

                var vote = record.Vote;
                if (vote == null)
                {
                    _logger.LogDebug($"Not processing record, vote = null");
                    return(false);
                }

                var pollSummary = await _storageService.GetPollSummary(vote.PollId);

                if (pollSummary == null)
                {
                    _logger.LogWarning($"Not processing record for poll {vote.PollId}, summary could not be identified");
                    return(false);
                }

                pollSummary.TotalVotes++;

                var pollOption = pollSummary.Options.FirstOrDefault(x => x.Option.Id == vote.OptionId);
                if (pollOption == null)
                {
                    _logger.LogWarning($"Specified poll option {vote.OptionId} not found");
                    return(false);
                }

                pollOption.VoteCounts++;

                // ReRank votes and compute ratios
                var rank = 0;
                foreach (var option in pollSummary.Options.OrderBy(x => x.VoteCounts))
                {
                    option.Rank  = rank;
                    option.Ratio = option.VoteCounts / pollSummary.TotalVotes;
                    rank++;
                }

                var didUpsert = await _storageService.UpsertPollSummary(pollSummary);

                if (!didUpsert)
                {
                    _logger.LogWarning("Error while upserting PollSummary");
                    return(false);
                }

                return(true);
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Error while processing voting record");
                return(false);
            }
            finally
            {
                _logger.LogDebug($"Finished processing voting record {record.Sequence} for user {record.Vote.UserId} on poll {record.Vote.PollId}");
            }
        }
Ejemplo n.º 5
0
        //TODO: User cannot vote when Event CurrentEpoch >= EpochNumber + 1
        public override Empty Vote(VoteInput input)
        {
            input.Topic = input.Topic.Trim();

            var votingEvent = AssertVotingEvent(input.Topic, input.Sponsor);

            Assert(votingEvent.Options.Contains(input.Option), $"Option {input.Option} not found.");
            if (votingEvent.Delegated)
            {
                Assert(input.Sponsor == Context.Sender, "Sender of delegated voting event must be the Sponsor.");
                Assert(input.Voter != null, "Voter cannot be null if voting event is delegated.");
                Assert(input.VoteId != null, "Vote Id cannot be null if voting event is delegated.");
            }
            else
            {
                input.Voter  = Context.Sender;
                input.VoteId = Context.TransactionId;
            }

            var votingRecord = new VotingRecord
            {
                Topic         = input.Topic,
                Sponsor       = input.Sponsor,
                Amount        = input.Amount,
                EpochNumber   = votingEvent.CurrentEpoch,
                Option        = input.Option,
                IsWithdrawn   = false,
                VoteTimestamp = Context.CurrentBlockTime.ToTimestamp(),
                Voter         = input.Voter,
                Currency      = votingEvent.AcceptedCurrency
            };

            // Update VotingResult based on this voting behaviour.
            var votingResultHash = Hash.FromMessage(new GetVotingResultInput
            {
                Sponsor     = input.Sponsor,
                Topic       = input.Topic,
                EpochNumber = votingEvent.CurrentEpoch
            });
            var votingResult = State.VotingResults[votingResultHash];

            if (!votingResult.Results.ContainsKey(input.Option))
            {
                votingResult.Results.Add(input.Option, 0);
            }
            var currentVotes = votingResult.Results[input.Option];

            votingResult.Results[input.Option] = currentVotes + input.Amount;

            // Update voting history
            var votingHistories = State.VotingHistoriesMap[votingRecord.Voter] ?? new VotingHistories
            {
                Voter = votingRecord.Voter
            };
            var votingEventHash = votingEvent.GetHash().ToHex();

            if (!votingHistories.Votes.ContainsKey(votingEventHash))
            {
                votingHistories.Votes[votingEventHash] = new VotingHistory
                {
                    ActiveVotes = { input.VoteId }
                };
                votingResult.VotersCount += 1;
            }
            else
            {
                votingHistories.Votes[votingEventHash].ActiveVotes.Add(input.VoteId);
            }

            State.VotingRecords[input.VoteId] = votingRecord;

            State.VotingResults[votingResultHash] = votingResult;

            State.VotingHistoriesMap[votingRecord.Voter] = votingHistories;

            if (!votingEvent.Delegated)
            {
                // Lock voted token.
                State.TokenContract.Lock.Send(new LockInput
                {
                    From   = votingRecord.Voter,
                    Symbol = votingEvent.AcceptedCurrency,
                    LockId = input.VoteId,
                    Amount = input.Amount,
                    To     = Context.Self,
                    Usage  = $"Voting for {input.Topic}"
                });
            }

            return(new Empty());
        }