public void MultiVote(Address from, string subject, PollVote[] choices) { Runtime.Expect(_pollMap.ContainsKey <string>(subject), "invalid poll subject"); Runtime.Expect(choices.Length > 0, "invalid number of choices"); var poll = FetchPoll(subject); Runtime.Expect(poll.state == PollState.Active, "poll not active"); switch (poll.kind) { case ConsensusKind.Validators: Runtime.Expect(Runtime.Nexus.IsKnownValidator(from), "must be primary or secondary validator"); var primaryValidators = Runtime.Nexus.GetPrimaryValidatorCount(); Runtime.Expect(primaryValidators >= 2, "not enough primary validators"); break; case ConsensusKind.Masters: Runtime.Expect(Runtime.Nexus.IsStakeMaster(from), "must be stake master"); var masters = Runtime.CallContext(Nexus.StakeContractName, nameof(StakeContract.GetMasterCount), from).AsNumber(); break; } Runtime.Expect(choices.Length <= poll.choicesPerUser, "too many choices"); Runtime.Expect(IsWitness(from), "invalid witness"); var presences = _presences.Get <Address, StorageList>(from); var count = presences.Count(); int index = -1; BigInteger round = 0; for (int i = 0; i < count; i++) { var presence = presences.Get <PollPresence>(i); if (presence.subject == subject) { index = -1; round = presence.round; break; } } if (index >= 0) { Runtime.Expect(round < poll.round, "already voted"); } BigInteger votingPower; if (poll.kind == ConsensusKind.Community) { votingPower = Runtime.CallContext(Nexus.StakeContractName, nameof(StakeContract.GetAddressVotingPower), from).AsNumber(); } else { votingPower = 100; } Runtime.Expect(votingPower > 0, "not enough voting power"); for (int i = 0; i < choices.Length; i++) { var votes = (votingPower * choices[i].percentage) / 100; Runtime.Expect(votes > 0, "choice percentage is too low"); var targetIndex = (int)choices[i].index; poll.entries[targetIndex].votes += votes; } poll.totalVotes += 1; _pollMap.Set <string, ConsensusPoll>(subject, poll); // finally add this voting round to the presences list var temp = new PollPresence() { subject = subject, round = poll.round, }; if (index >= 0) { presences.Replace <PollPresence>(index, temp); } else { presences.Add(temp); } Runtime.Notify(EventKind.PollVote, from, subject); }
public void MultiVote(Address from, string subject, PollVote[] choices) { Runtime.Expect(_pollMap.ContainsKey <string>(subject), "invalid subject"); Runtime.Expect(choices.Length > 0, "invalid number of choices"); var poll = FetchPoll(subject); Runtime.Expect(poll.state == PollState.Active, "poll not active"); Runtime.Expect(choices.Length <= poll.votesPerUser, "too many choices"); Runtime.Expect(IsWitness(from), "invalid witness"); var presences = _presences.Get <Address, StorageList>(from); var count = presences.Count(); int index = -1; BigInteger round = 0; for (int i = 0; i < count; i++) { var presence = presences.Get <PollPresence>(i); if (presence.subject == subject) { index = -1; round = presence.round; break; } } if (index >= 0) { Runtime.Expect(round < poll.round, "already voted"); } BigInteger votingPower; if (poll.kind == ConsensusKind.Validators) { votingPower = 100; } else { votingPower = (BigInteger)Runtime.CallContext("energy", "GetAddressVotingPower", from); } Runtime.Expect(votingPower > 0, "not enough voting power"); for (int i = 0; i < choices.Length; i++) { var votes = (votingPower * choices[i].percentage) / 100; Runtime.Expect(votes > 0, "choice percentage is too low"); var targetIndex = (int)choices[i].index; poll.entries[targetIndex].votes += votes; } poll.totalVotes += 1; _pollMap.Set <string, ConsensusPoll>(subject, poll); // finally add this voting round to the presences list var temp = new PollPresence() { subject = subject, round = poll.round, }; if (index >= 0) { presences.Replace <PollPresence>(index, temp); } else { presences.Add(temp); } Runtime.Notify(EventKind.PollVote, from, subject); }