Persist EvaluatedProposalList

This commit is contained in:
Manfred Karrer 2018-10-08 19:47:54 -05:00
parent d279dae032
commit 4cc17feace
No known key found for this signature in database
GPG Key ID: 401250966A6B2C46
10 changed files with 209 additions and 23 deletions

View File

@ -932,6 +932,7 @@ message PersistableEnvelope {
MeritList merit_list = 23; MeritList merit_list = 23;
BondedRoleList bonded_role_list = 24; BondedRoleList bonded_role_list = 24;
RemovedAssetList removed_asset_list = 25; RemovedAssetList removed_asset_list = 25;
EvaluatedProposalList evaluated_proposal_list = 26;
} }
} }
@ -1625,6 +1626,26 @@ message MeritList {
repeated Merit merit = 1; repeated Merit merit = 1;
} }
message ProposalVoteResult {
Proposal proposal = 1;
int64 stake_of_Accepted_votes = 2;
int64 stake_of_Rejected_votes = 3;
int32 num_accepted_votes = 4;
int32 num_rejected_votes = 5;
int32 num_ignored_votes = 6;
}
message EvaluatedProposal {
bool is_accepted = 1;
ProposalVoteResult proposal_vote_result = 2;
int64 required_quorum = 3;
int64 required_threshold = 4;
}
message EvaluatedProposalList {
repeated EvaluatedProposal evaluated_proposal = 1;
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Misc // Misc
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -23,6 +23,7 @@ import bisq.core.dao.governance.ballot.BallotListService;
import bisq.core.dao.governance.blindvote.MyBlindVoteListService; import bisq.core.dao.governance.blindvote.MyBlindVoteListService;
import bisq.core.dao.governance.myvote.MyVoteListService; import bisq.core.dao.governance.myvote.MyVoteListService;
import bisq.core.dao.governance.role.BondedRolesService; import bisq.core.dao.governance.role.BondedRolesService;
import bisq.core.dao.governance.voteresult.VoteResultService;
import bisq.core.filter.FilterManager; import bisq.core.filter.FilterManager;
import bisq.core.payment.AccountAgeWitnessService; import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.trade.statistics.TradeStatisticsManager;
@ -52,7 +53,8 @@ public class AppSetupWithP2PAndDAO extends AppSetupWithP2P {
BallotListService ballotListService, BallotListService ballotListService,
MyBlindVoteListService myBlindVoteListService, MyBlindVoteListService myBlindVoteListService,
BondedRolesService bondedRolesService, BondedRolesService bondedRolesService,
AssetService assetService) { AssetService assetService,
VoteResultService voteResultService) {
super(encryptionService, super(encryptionService,
keyRing, keyRing,
p2PService, p2PService,
@ -67,6 +69,7 @@ public class AppSetupWithP2PAndDAO extends AppSetupWithP2P {
persistedDataHosts.add(myBlindVoteListService); persistedDataHosts.add(myBlindVoteListService);
persistedDataHosts.add(bondedRolesService); persistedDataHosts.add(bondedRolesService);
persistedDataHosts.add(assetService); persistedDataHosts.add(assetService);
persistedDataHosts.add(voteResultService);
} }
@Override @Override

View File

@ -19,10 +19,14 @@ package bisq.core.dao.governance.voteresult;
import bisq.core.dao.governance.proposal.Proposal; import bisq.core.dao.governance.proposal.Proposal;
import bisq.common.proto.persistable.PersistablePayload;
import io.bisq.generated.protobuffer.PB;
import lombok.Value; import lombok.Value;
@Value @Value
public class EvaluatedProposal { public class EvaluatedProposal implements PersistablePayload {
private final boolean isAccepted; private final boolean isAccepted;
private final ProposalVoteResult proposalVoteResult; private final ProposalVoteResult proposalVoteResult;
private final long requiredQuorum; private final long requiredQuorum;
@ -35,6 +39,33 @@ public class EvaluatedProposal {
this.requiredThreshold = requiredThreshold; this.requiredThreshold = requiredThreshold;
} }
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public PB.EvaluatedProposal toProtoMessage() {
PB.EvaluatedProposal.Builder builder = PB.EvaluatedProposal.newBuilder()
.setIsAccepted(isAccepted)
.setProposalVoteResult(proposalVoteResult.toProtoMessage())
.setRequiredQuorum(requiredQuorum)
.setRequiredThreshold(requiredThreshold);
return builder.build();
}
public static EvaluatedProposal fromProto(PB.EvaluatedProposal evaluatedProposal) {
return new EvaluatedProposal(evaluatedProposal.getIsAccepted(),
ProposalVoteResult.fromProto(evaluatedProposal.getProposalVoteResult()),
evaluatedProposal.getRequiredQuorum(),
evaluatedProposal.getRequiredThreshold());
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public Proposal getProposal() { public Proposal getProposal() {
return proposalVoteResult.getProposal(); return proposalVoteResult.getProposal();
} }

View File

@ -0,0 +1,76 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.dao.governance.voteresult;
import bisq.core.dao.governance.ConsensusCritical;
import bisq.common.proto.persistable.PersistableList;
import io.bisq.generated.protobuffer.PB;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
/**
* PersistableEnvelope wrapper for list of evaluatedProposals.
*/
@EqualsAndHashCode(callSuper = true)
public class EvaluatedProposalList extends PersistableList<EvaluatedProposal> implements ConsensusCritical {
public EvaluatedProposalList(List<EvaluatedProposal> list) {
super(list);
}
public EvaluatedProposalList() {
super();
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public PB.PersistableEnvelope toProtoMessage() {
return PB.PersistableEnvelope.newBuilder().setEvaluatedProposalList(getBuilder()).build();
}
public PB.EvaluatedProposalList.Builder getBuilder() {
return PB.EvaluatedProposalList.newBuilder()
.addAllEvaluatedProposal(getList().stream()
.map(EvaluatedProposal::toProtoMessage)
.collect(Collectors.toList()));
}
public static EvaluatedProposalList fromProto(PB.EvaluatedProposalList proto) {
return new EvaluatedProposalList(new ArrayList<>(proto.getEvaluatedProposalList().stream()
.map(EvaluatedProposal::fromProto)
.collect(Collectors.toList())));
}
@Override
public String toString() {
return "List of proposalTxId's in EvaluatedProposalList: " + getList().stream()
.map(EvaluatedProposal::getProposalTxId)
.collect(Collectors.toList());
}
}

View File

@ -19,6 +19,10 @@ package bisq.core.dao.governance.voteresult;
import bisq.core.dao.governance.proposal.Proposal; import bisq.core.dao.governance.proposal.Proposal;
import bisq.common.proto.persistable.PersistablePayload;
import io.bisq.generated.protobuffer.PB;
import lombok.Value; import lombok.Value;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -26,7 +30,7 @@ import static com.google.common.base.Preconditions.checkArgument;
@Value @Value
@Slf4j @Slf4j
public class ProposalVoteResult { public class ProposalVoteResult implements PersistablePayload {
private final Proposal proposal; private final Proposal proposal;
private final long stakeOfAcceptedVotes; private final long stakeOfAcceptedVotes;
private final long stakeOfRejectedVotes; private final long stakeOfRejectedVotes;
@ -44,6 +48,36 @@ public class ProposalVoteResult {
this.numIgnoredVotes = numIgnoredVotes; this.numIgnoredVotes = numIgnoredVotes;
} }
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public PB.ProposalVoteResult toProtoMessage() {
PB.ProposalVoteResult.Builder builder = PB.ProposalVoteResult.newBuilder()
.setProposal(proposal.toProtoMessage())
.setStakeOfAcceptedVotes(stakeOfAcceptedVotes)
.setStakeOfRejectedVotes(stakeOfRejectedVotes)
.setNumAcceptedVotes(numAcceptedVotes)
.setNumRejectedVotes(numRejectedVotes)
.setNumIgnoredVotes(numIgnoredVotes);
return builder.build();
}
public static ProposalVoteResult fromProto(PB.ProposalVoteResult proposalVoteResult) {
return new ProposalVoteResult(Proposal.fromProto(proposalVoteResult.getProposal()),
proposalVoteResult.getStakeOfAcceptedVotes(),
proposalVoteResult.getStakeOfRejectedVotes(),
proposalVoteResult.getNumAcceptedVotes(),
proposalVoteResult.getNumRejectedVotes(),
proposalVoteResult.getNumIgnoredVotes());
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public int getNumActiveVotes() { public int getNumActiveVotes() {
return numAcceptedVotes + numRejectedVotes; return numAcceptedVotes + numRejectedVotes;
} }

View File

@ -17,6 +17,7 @@
package bisq.core.dao.governance.voteresult; package bisq.core.dao.governance.voteresult;
import bisq.core.app.BisqEnvironment;
import bisq.core.dao.DaoSetupService; import bisq.core.dao.DaoSetupService;
import bisq.core.dao.governance.asset.AssetService; import bisq.core.dao.governance.asset.AssetService;
import bisq.core.dao.governance.ballot.Ballot; import bisq.core.dao.governance.ballot.Ballot;
@ -55,6 +56,8 @@ import bisq.core.locale.CurrencyUtil;
import bisq.network.p2p.storage.P2PDataStorage; import bisq.network.p2p.storage.P2PDataStorage;
import bisq.common.proto.persistable.PersistedDataHost;
import bisq.common.storage.Storage;
import bisq.common.util.Utilities; import bisq.common.util.Utilities;
import javax.inject.Inject; import javax.inject.Inject;
@ -92,7 +95,7 @@ import static com.google.common.base.Preconditions.checkArgument;
* the missing blindVotes from the network. * the missing blindVotes from the network.
*/ */
@Slf4j @Slf4j
public class VoteResultService implements BsqStateListener, DaoSetupService { public class VoteResultService implements BsqStateListener, DaoSetupService, PersistedDataHost {
private final VoteRevealService voteRevealService; private final VoteRevealService voteRevealService;
private final ProposalListPresentation proposalListPresentation; private final ProposalListPresentation proposalListPresentation;
private final BsqStateService bsqStateService; private final BsqStateService bsqStateService;
@ -102,13 +105,14 @@ public class VoteResultService implements BsqStateListener, DaoSetupService {
private final BondedRolesService bondedRolesService; private final BondedRolesService bondedRolesService;
private final IssuanceService issuanceService; private final IssuanceService issuanceService;
private final AssetService assetService; private final AssetService assetService;
private final Storage<EvaluatedProposalList> storage;
@Getter @Getter
private final ObservableList<VoteResultException> voteResultExceptions = FXCollections.observableArrayList(); private final ObservableList<VoteResultException> voteResultExceptions = FXCollections.observableArrayList();
// Use a list to have order by cycle // Use a list to have order by cycle
// TODO persist, PB
@Getter @Getter
private final Set<EvaluatedProposal> allEvaluatedProposals = new HashSet<>(); private final EvaluatedProposalList evaluatedProposalList = new EvaluatedProposalList();
@Getter @Getter
private final Set<DecryptedBallotsWithMerits> allDecryptedBallotsWithMerits = new HashSet<>(); private final Set<DecryptedBallotsWithMerits> allDecryptedBallotsWithMerits = new HashSet<>();
@ -126,7 +130,8 @@ public class VoteResultService implements BsqStateListener, DaoSetupService {
BlindVoteListService blindVoteListService, BlindVoteListService blindVoteListService,
BondedRolesService bondedRolesService, BondedRolesService bondedRolesService,
IssuanceService issuanceService, IssuanceService issuanceService,
AssetService assetService) { AssetService assetService,
Storage<EvaluatedProposalList> storage) {
this.voteRevealService = voteRevealService; this.voteRevealService = voteRevealService;
this.proposalListPresentation = proposalListPresentation; this.proposalListPresentation = proposalListPresentation;
this.bsqStateService = bsqStateService; this.bsqStateService = bsqStateService;
@ -136,6 +141,23 @@ public class VoteResultService implements BsqStateListener, DaoSetupService {
this.bondedRolesService = bondedRolesService; this.bondedRolesService = bondedRolesService;
this.issuanceService = issuanceService; this.issuanceService = issuanceService;
this.assetService = assetService; this.assetService = assetService;
this.storage = storage;
}
///////////////////////////////////////////////////////////////////////////////////////////
// PersistedDataHost
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void readPersisted() {
if (BisqEnvironment.isDAOActivatedAndBaseCurrencySupportingBsq()) {
EvaluatedProposalList persisted = storage.initAndGetPersisted(evaluatedProposalList, 100);
if (persisted != null) {
evaluatedProposalList.clear();
evaluatedProposalList.addAll(persisted.getList());
}
}
} }
@ -154,19 +176,6 @@ public class VoteResultService implements BsqStateListener, DaoSetupService {
} }
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public Set<EvaluatedProposal> getAllAcceptedEvaluatedProposals() {
return getAcceptedEvaluatedProposals(allEvaluatedProposals);
}
public Set<EvaluatedProposal> getAllRejectedEvaluatedProposals() {
return getRejectedEvaluatedProposals(allEvaluatedProposals);
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// BsqStateListener // BsqStateListener
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -221,7 +230,10 @@ public class VoteResultService implements BsqStateListener, DaoSetupService {
Set<EvaluatedProposal> acceptedEvaluatedProposals = getAcceptedEvaluatedProposals(evaluatedProposals); Set<EvaluatedProposal> acceptedEvaluatedProposals = getAcceptedEvaluatedProposals(evaluatedProposals);
applyAcceptedProposals(acceptedEvaluatedProposals, chainHeight); applyAcceptedProposals(acceptedEvaluatedProposals, chainHeight);
allEvaluatedProposals.addAll(evaluatedProposals); evaluatedProposals.stream()
.filter(e -> !evaluatedProposalList.getList().contains(e))
.forEach(evaluatedProposalList::add);
persist();
log.info("processAllVoteResults completed"); log.info("processAllVoteResults completed");
} else { } else {
log.warn("Our list of received blind votes do not match the list from the majority of voters."); log.warn("Our list of received blind votes do not match the list from the majority of voters.");
@ -689,6 +701,10 @@ public class VoteResultService implements BsqStateListener, DaoSetupService {
return periodService.getFirstBlockOfPhase(chainHeight, DaoPhase.Phase.RESULT) == chainHeight; return periodService.getFirstBlockOfPhase(chainHeight, DaoPhase.Phase.RESULT) == chainHeight;
} }
private void persist() {
storage.queueUpForSave(20);
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Inner classes // Inner classes

View File

@ -30,6 +30,7 @@ import bisq.core.dao.governance.proposal.MyProposalList;
import bisq.core.dao.governance.proposal.storage.appendonly.ProposalStore; import bisq.core.dao.governance.proposal.storage.appendonly.ProposalStore;
import bisq.core.dao.governance.proposal.storage.temp.TempProposalStore; import bisq.core.dao.governance.proposal.storage.temp.TempProposalStore;
import bisq.core.dao.governance.role.BondedRoleList; import bisq.core.dao.governance.role.BondedRoleList;
import bisq.core.dao.governance.voteresult.EvaluatedProposalList;
import bisq.core.dao.state.BsqState; import bisq.core.dao.state.BsqState;
import bisq.core.payment.AccountAgeWitnessStore; import bisq.core.payment.AccountAgeWitnessStore;
import bisq.core.payment.PaymentAccountList; import bisq.core.payment.PaymentAccountList;
@ -135,6 +136,8 @@ public class CorePersistenceProtoResolver extends CoreProtoResolver implements P
return BondedRoleList.fromProto(proto.getBondedRoleList()); return BondedRoleList.fromProto(proto.getBondedRoleList());
case REMOVED_ASSET_LIST: case REMOVED_ASSET_LIST:
return RemovedAssetsList.fromProto(proto.getRemovedAssetList()); return RemovedAssetsList.fromProto(proto.getRemovedAssetList());
case EVALUATED_PROPOSAL_LIST:
return EvaluatedProposalList.fromProto(proto.getEvaluatedProposalList());
default: default:
throw new ProtobufferRuntimeException("Unknown proto message case(PB.PersistableEnvelope). " + throw new ProtobufferRuntimeException("Unknown proto message case(PB.PersistableEnvelope). " +
"messageCase=" + proto.getMessageCase() + "; proto raw data=" + proto.toString()); "messageCase=" + proto.getMessageCase() + "; proto raw data=" + proto.toString());

View File

@ -26,6 +26,7 @@ import bisq.core.dao.governance.blindvote.MyBlindVoteListService;
import bisq.core.dao.governance.myvote.MyVoteListService; import bisq.core.dao.governance.myvote.MyVoteListService;
import bisq.core.dao.governance.proposal.MyProposalListService; import bisq.core.dao.governance.proposal.MyProposalListService;
import bisq.core.dao.governance.role.BondedRolesService; import bisq.core.dao.governance.role.BondedRolesService;
import bisq.core.dao.governance.voteresult.VoteResultService;
import bisq.core.offer.OpenOfferManager; import bisq.core.offer.OpenOfferManager;
import bisq.core.trade.TradeManager; import bisq.core.trade.TradeManager;
import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.trade.closed.ClosedTradableManager;
@ -69,6 +70,7 @@ public class CorePersistedDataHost {
persistedDataHosts.add(injector.getInstance(MyProposalListService.class)); persistedDataHosts.add(injector.getInstance(MyProposalListService.class));
persistedDataHosts.add(injector.getInstance(BondedRolesService.class)); persistedDataHosts.add(injector.getInstance(BondedRolesService.class));
persistedDataHosts.add(injector.getInstance(AssetService.class)); persistedDataHosts.add(injector.getInstance(AssetService.class));
persistedDataHosts.add(injector.getInstance(VoteResultService.class));
} }
return persistedDataHosts; return persistedDataHosts;
} }

View File

@ -418,7 +418,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
private void onSelectProposal(ProposalsListItem item) { private void onSelectProposal(ProposalsListItem item) {
selectedItem = item; selectedItem = item;
if (selectedItem != null) { if (selectedItem != null) {
EvaluatedProposal evaluatedProposal = voteResultService.getAllEvaluatedProposals().stream() EvaluatedProposal evaluatedProposal = voteResultService.getEvaluatedProposalList().stream()
.filter(e -> daoFacade.isTxInCorrectCycle(e.getProposal().getTxId(), .filter(e -> daoFacade.isTxInCorrectCycle(e.getProposal().getTxId(),
daoFacade.getChainHeight())) daoFacade.getChainHeight()))
.filter(e -> e.getProposalTxId().equals(selectedItem.getProposal().getTxId())) .filter(e -> e.getProposalTxId().equals(selectedItem.getProposal().getTxId()))

View File

@ -245,7 +245,7 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements B
.filter(proposal -> cycleService.isTxInCycle(cycle, proposal.getTxId())) .filter(proposal -> cycleService.isTxInCycle(cycle, proposal.getTxId()))
.collect(Collectors.toList()); .collect(Collectors.toList());
List<EvaluatedProposal> evaluatedProposalsForCycle = voteResultService.getAllEvaluatedProposals().stream() List<EvaluatedProposal> evaluatedProposalsForCycle = voteResultService.getEvaluatedProposalList().stream()
.filter(evaluatedProposal -> cycleService.isTxInCycle(cycle, evaluatedProposal.getProposal().getTxId())) .filter(evaluatedProposal -> cycleService.isTxInCycle(cycle, evaluatedProposal.getProposal().getTxId()))
.collect(Collectors.toList()); .collect(Collectors.toList());