use of bisq.core.dao.governance.blindvote.VoteWithProposalTxIdList in project bisq-core by bisq-network.
the class VoteResultService method createBallotList.
private BallotList createBallotList(VoteWithProposalTxIdList voteWithProposalTxIdList) throws MissingBallotException {
// We convert the list to a map with proposalTxId as key and the vote as value
Map<String, Vote> voteByTxIdMap = voteWithProposalTxIdList.stream().filter(voteWithProposalTxId -> voteWithProposalTxId.getVote() != null).collect(Collectors.toMap(VoteWithProposalTxId::getProposalTxId, VoteWithProposalTxId::getVote));
// We make a map with proposalTxId as key and the ballot as value out of our stored ballot list
Map<String, Ballot> ballotByTxIdMap = ballotListService.getBallotList().stream().collect(Collectors.toMap(Ballot::getTxId, ballot -> ballot));
List<String> missingBallots = new ArrayList<>();
List<Ballot> ballots = voteByTxIdMap.entrySet().stream().map(entry -> {
String txId = entry.getKey();
if (ballotByTxIdMap.containsKey(txId)) {
// why not use proposalList?
Ballot ballot = ballotByTxIdMap.get(txId);
// We create a new Ballot with the proposal from the ballot list and the vote from our decrypted votes
Vote vote = entry.getValue();
// received from the network?
return new Ballot(ballot.getProposal(), vote);
} else {
// We got a vote but we don't have the ballot (which includes the proposal)
// We add it to the missing list to handle it as exception later. We want all missing data so we
// do not throw here.
missingBallots.add(txId);
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
if (!missingBallots.isEmpty())
throw new MissingBallotException(ballots, missingBallots);
// Let's keep the data more deterministic by sorting it by txId. Though we are not using the sorting.
ballots.sort(Comparator.comparing(Ballot::getTxId));
return new BallotList(ballots);
}
use of bisq.core.dao.governance.blindvote.VoteWithProposalTxIdList in project bisq-core by bisq-network.
the class VoteResultService method getDecryptedBallotsWithMeritsSet.
private Set<DecryptedBallotsWithMerits> getDecryptedBallotsWithMeritsSet(int chainHeight) {
// We want all voteRevealTxOutputs which are in current cycle we are processing.
return bsqStateService.getVoteRevealOpReturnTxOutputs().stream().filter(txOutput -> periodService.isTxInCorrectCycle(txOutput.getTxId(), chainHeight)).map(txOutput -> {
// TODO make method
byte[] opReturnData = txOutput.getOpReturnData();
String voteRevealTxId = txOutput.getTxId();
Optional<Tx> optionalVoteRevealTx = bsqStateService.getTx(voteRevealTxId);
if (!optionalVoteRevealTx.isPresent()) {
log.error("optionalVoteRevealTx is not present. voteRevealTxId={}", voteRevealTxId);
// TODO throw exception
return null;
}
Tx voteRevealTx = optionalVoteRevealTx.get();
try {
// TODO maybe verify version in opReturn
byte[] hashOfBlindVoteList = VoteResultConsensus.getHashOfBlindVoteList(opReturnData);
SecretKey secretKey = VoteResultConsensus.getSecretKey(opReturnData);
TxOutput blindVoteStakeOutput = VoteResultConsensus.getConnectedBlindVoteStakeOutput(voteRevealTx, bsqStateService);
long blindVoteStake = blindVoteStakeOutput.getValue();
Tx blindVoteTx = VoteResultConsensus.getBlindVoteTx(blindVoteStakeOutput, bsqStateService, periodService, chainHeight);
String blindVoteTxId = blindVoteTx.getId();
// Here we deal with eventual consistency of the p2p network data!
// TODO make more clear we are in p2p domain now
List<BlindVote> blindVoteList = BlindVoteConsensus.getSortedBlindVoteListOfCycle(blindVoteListService);
Optional<BlindVote> optionalBlindVote = blindVoteList.stream().filter(blindVote -> blindVote.getTxId().equals(blindVoteTxId)).findAny();
if (optionalBlindVote.isPresent()) {
BlindVote blindVote = optionalBlindVote.get();
VoteWithProposalTxIdList voteWithProposalTxIdList = VoteResultConsensus.decryptVotes(blindVote.getEncryptedVotes(), secretKey);
MeritList meritList = MeritConsensus.decryptMeritList(blindVote.getEncryptedMeritList(), secretKey);
// We lookup for the proposals we have in our local list which match the txId from the
// voteWithProposalTxIdList and create a ballot list with the proposal and the vote from
// the voteWithProposalTxIdList
BallotList ballotList = createBallotList(voteWithProposalTxIdList);
return new DecryptedBallotsWithMerits(hashOfBlindVoteList, voteRevealTxId, blindVoteTxId, blindVoteStake, ballotList, meritList);
} else {
// TODO handle recovering
log.warn("We have a blindVoteTx but we do not have the corresponding blindVote in our local list.\n" + "That can happen if the blindVote item was not properly broadcast. We will go on " + "and see if that blindVote was part of the majority data view. If so we should " + "recover the missing blind vote by a request to our peers. blindVoteTxId={}", blindVoteTxId);
return null;
}
} catch (MissingBallotException e) {
// TODO handle case that we are missing proposals
log.error("We are missing proposals to create the vote result: " + e.toString());
return null;
} catch (Throwable e) {
log.error("Could not create DecryptedBallotsWithMerits: " + e.toString());
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toSet());
}
Aggregations