Merge pull request #2515 from ManfredKarrer/make-vote-result-json-determinisitic

Make vote result json deterministic
This commit is contained in:
Manfred Karrer 2019-03-08 13:06:23 -05:00 committed by GitHub
commit 257550ac81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 32 deletions

View file

@ -51,6 +51,7 @@ import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
@ -482,9 +483,18 @@ public class BSFormatter {
}
public String formatDateTime(Date date) {
return formatDateTime(date,
DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale()),
DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale()));
return formatDateTime(date, true);
}
public String formatDateTime(Date date, boolean useLocaleAndLocalTimezone) {
Locale locale = useLocaleAndLocalTimezone ? getLocale() : Locale.US;
DateFormat dateInstance = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
DateFormat timeInstance = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
if (!useLocaleAndLocalTimezone) {
dateInstance.setTimeZone(TimeZone.getTimeZone("UTC"));
timeInstance.setTimeZone(TimeZone.getTimeZone("UTC"));
}
return formatDateTime(date, dateInstance, timeInstance);
}
public String formatDateTime(Date date, DateFormat dateFormatter, DateFormat timeFormatter) {

View file

@ -46,10 +46,16 @@ public class CycleListItem {
}
public String getCycle() {
int displayIndex = resultsOfCycle.getCycleIndex() + 1;
return Res.get("dao.results.results.table.item.cycle", getCycleIndex(), getCycleDateTime(true));
}
public String getCycleDateTime(boolean useLocaleAndLocalTimezone) {
long cycleStartTime = resultsOfCycle.getCycleStartTime();
String dateTime = cycleStartTime > 0 ? bsqFormatter.formatDateTime(new Date(cycleStartTime)) : Res.get("shared.na");
return Res.get("dao.results.results.table.item.cycle", displayIndex, dateTime);
return cycleStartTime > 0 ? bsqFormatter.formatDateTime(new Date(cycleStartTime), useLocaleAndLocalTimezone) : Res.get("shared.na");
}
public int getCycleIndex() {
return resultsOfCycle.getCycleIndex() + 1;
}
public String getNumProposals() {

View file

@ -109,6 +109,10 @@ public class ProposalListItem {
}
public static String getProposalDetails(EvaluatedProposal evaluatedProposal, BsqFormatter bsqFormatter) {
return getProposalDetails(evaluatedProposal, bsqFormatter, true);
}
public static String getProposalDetails(EvaluatedProposal evaluatedProposal, BsqFormatter bsqFormatter, boolean useDisplayString) {
Proposal proposal = evaluatedProposal.getProposal();
switch (proposal.getType()) {
case COMPENSATION_REQUEST:
@ -121,11 +125,12 @@ public class ProposalListItem {
return bsqFormatter.formatCoinWithCode(requestedBsq);
case CHANGE_PARAM:
ChangeParamProposal changeParamProposal = (ChangeParamProposal) proposal;
return changeParamProposal.getParam().getDisplayString();
return useDisplayString ? changeParamProposal.getParam().getDisplayString() : changeParamProposal.getParam().name();
case BONDED_ROLE:
RoleProposal roleProposal = (RoleProposal) proposal;
Role role = roleProposal.getRole();
return Res.get("dao.bond.bondedRoleType." + role.getBondedRoleType().name());
String name = role.getBondedRoleType().name();
return useDisplayString ? Res.get("dao.bond.bondedRoleType." + name) : name;
case CONFISCATE_BOND:
ConfiscateBondProposal confiscateBondProposal = (ConfiscateBondProposal) proposal;
// TODO add info to bond

View file

@ -952,13 +952,12 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
sortedCycleListItemList.sorted(Comparator.comparing(CycleListItem::getCycleStartTime)).forEach(cycle -> {
JsonObject cycleJson = new JsonObject();
cycleJson.addProperty("cycleIndex", cycle.getResultsOfCycle().getCycleIndex());
cycleJson.addProperty("cycle", cycle.getCycle());
cycleJson.addProperty("proposalsCount", cycle.getNumProposals());
cycleJson.addProperty("cycleIndex", cycle.getCycleIndex());
cycleJson.addProperty("cycleDateTime", cycle.getCycleDateTime(false));
cycleJson.addProperty("votesCount", cycle.getNumVotesAsString());
cycleJson.addProperty("voteWeight", cycle.getMeritAndStake());
cycleJson.addProperty("issuance", cycle.getIssuance());
cycleJson.addProperty("startDate", cycle.getCycleStartTime());
cycleJson.addProperty("startTime", cycle.getCycleStartTime());
cycleJson.addProperty("totalAcceptedVotes", cycle.getResultsOfCycle().getNumAcceptedVotes());
cycleJson.addProperty("totalRejectedVotes", cycle.getResultsOfCycle().getNumRejectedVotes());
@ -969,11 +968,11 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
evaluatedProposals.forEach(proposal -> {
JsonObject proposalJson = new JsonObject();
proposalJson.addProperty("dateTime", bsqFormatter.formatDateTime(proposal.getProposal().getCreationDate()));
proposalJson.addProperty("dateTime", bsqFormatter.formatDateTime(proposal.getProposal().getCreationDate(), false));
proposalJson.addProperty("name", proposal.getProposal().getName());
proposalJson.addProperty("link", proposal.getProposal().getLink());
proposalJson.addProperty("proposalType", proposal.getProposal().getType().getShortDisplayName());
proposalJson.addProperty("details", ProposalListItem.getProposalDetails(proposal, bsqFormatter));
proposalJson.addProperty("proposalType", proposal.getProposal().getType().name());
proposalJson.addProperty("details", ProposalListItem.getProposalDetails(proposal, bsqFormatter, false));
proposalJson.addProperty("voteResult", proposal.isAccepted() ? "Accepted" : "Rejected");
proposalJson.addProperty("txId", proposal.getProposalTxId());
proposalJson.addProperty("requiredQuorum", proposal.getRequiredQuorum());
@ -990,7 +989,7 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
switch (proposal.getProposal().getType()) {
case BONDED_ROLE:
RoleProposal roleProposal = (RoleProposal) proposal.getProposal();
proposalJson.addProperty("roleType", roleProposal.getRole().getBondedRoleType().getDisplayString());
proposalJson.addProperty("roleType", roleProposal.getRole().getBondedRoleType().name());
proposalJson.addProperty("requiredBond", roleProposal.getRole().getBondedRoleType().getRequiredBond());
proposalJson.addProperty("allowMultipleHolders", roleProposal.getRole().getBondedRoleType().isAllowMultipleHolders());
proposalJson.addProperty("unlockTimeInBlocks", roleProposal.getRole().getBondedRoleType().getUnlockTimeInBlocks());
@ -998,7 +997,7 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
break;
case CHANGE_PARAM:
ChangeParamProposal changeParamProposal = (ChangeParamProposal) proposal.getProposal();
proposalJson.addProperty("param", changeParamProposal.getParam().getDisplayString());
proposalJson.addProperty("param", changeParamProposal.getParam().name());
proposalJson.addProperty("paramValue", changeParamProposal.getParamValue());
proposalJson.addProperty("paramDefaultValue", changeParamProposal.getParam().getDefaultValue());
proposalJson.addProperty("paramMaxDecrease", changeParamProposal.getParam().getMaxDecrease());
@ -1027,26 +1026,33 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
JsonArray votesArray = new JsonArray();
evaluatedProposals.stream()
.filter(evaluatedProposal -> evaluatedProposal.getProposal().equals(proposal.getProposal()))
.forEach(evaluatedProposal ->
cycle.getResultsOfCycle().getDecryptedVotesForCycle().forEach(decryptedBallotsWithMerits -> {
JsonObject voteJson = new JsonObject();
Optional<Vote> vote = decryptedBallotsWithMerits.getVote(proposal.getProposalTxId());
if (vote.isPresent())
voteJson.addProperty("vote", vote.get().isAccepted() ? "Accepted" : "Rejected");
else
voteJson.addProperty("vote", "Ignored");
.forEach(evaluatedProposal -> {
List<DecryptedBallotsWithMerits> decryptedVotesForCycle = cycle.getResultsOfCycle().getDecryptedVotesForCycle();
// Make sure the votes are sorted so we can easier compare json files from different users
decryptedVotesForCycle.sort(Comparator.comparing(DecryptedBallotsWithMerits::getBlindVoteTxId));
decryptedVotesForCycle.forEach(decryptedBallotsWithMerits -> {
JsonObject voteJson = new JsonObject();
Optional<Vote> vote = decryptedBallotsWithMerits.getVote(proposal.getProposalTxId());
if (vote.isPresent())
voteJson.addProperty("vote", vote.get().isAccepted() ? "Accepted" : "Rejected");
else
voteJson.addProperty("vote", "Ignored");
voteJson.addProperty("voteWeight", decryptedBallotsWithMerits.getStake());
voteJson.addProperty("stake", decryptedBallotsWithMerits.getStake());
voteJson.addProperty("blindTxId", decryptedBallotsWithMerits.getBlindVoteTxId());
voteJson.addProperty("revealTxId", decryptedBallotsWithMerits.getVoteRevealTxId());
voteJson.addProperty("voteWeight", decryptedBallotsWithMerits.getMerit(daoStateService));
voteJson.addProperty("stake", decryptedBallotsWithMerits.getStake());
voteJson.addProperty("blindTxId", decryptedBallotsWithMerits.getBlindVoteTxId());
voteJson.addProperty("revealTxId", decryptedBallotsWithMerits.getVoteRevealTxId());
votesArray.add(voteJson);
}));
votesArray.add(voteJson);
});
});
proposalJson.addProperty("numberOfVotes", votesArray.size());
proposalJson.add("votes", votesArray);
proposalsArray.add(proposalJson);
proposalsArray.add(proposalJson);
});
cycleJson.addProperty("numberOfProposals", proposalsArray.size());
cycleJson.add("proposals", proposalsArray);
cyclesArray.add(cycleJson);
});