use of bisq.core.dao.governance.blindvote.BlindVote 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());
}
use of bisq.core.dao.governance.blindvote.BlindVote in project bisq-core by bisq-network.
the class VoteRevealService method revealVote.
private void revealVote(MyVote myVote, int chainHeight) throws IOException, WalletException, InsufficientMoneyException, TransactionVerificationException, VoteRevealException {
// We collect all valid blind vote items we received via the p2p network.
// It might be that different nodes have a different collection of those items.
// To ensure we get a consensus of the data for later calculating the result we will put a hash of each
// voters blind vote collection into the opReturn data and check for a majority at issuance time.
// The voters "vote" with their stake at the reveal tx for their version of the blind vote collection.
// TODO make more clear by using param like here:
/* List<BlindVote> blindVotes = BlindVoteConsensus.getSortedBlindVoteListOfCycle(blindVoteListService);
VoteRevealConsensus.getHashOfBlindVoteList(blindVotes);*/
byte[] hashOfBlindVoteList = getHashOfBlindVoteList();
log.info("Sha256Ripemd160 hash of hashOfBlindVoteList " + Utilities.bytesAsHexString(hashOfBlindVoteList));
byte[] opReturnData = VoteRevealConsensus.getOpReturnData(hashOfBlindVoteList, myVote.getSecretKey());
// We search for my unspent stake output.
// myVote is already tested if it is in current cycle at maybeRevealVotes
// We expect that the blind vote tx and stake output is available. If not we throw an exception.
TxOutput stakeTxOutput = bsqStateService.getUnspentBlindVoteStakeTxOutputs().stream().filter(txOutput -> txOutput.getTxId().equals(myVote.getTxId())).findFirst().orElseThrow(() -> new VoteRevealException("stakeTxOutput is not found for myVote.", myVote));
// TODO is phase check needed and done in parser still?
if (periodService.isTxInCorrectCycle(stakeTxOutput.getTxId(), chainHeight)) {
Transaction voteRevealTx = getVoteRevealTx(stakeTxOutput, opReturnData);
log.info("voteRevealTx={}", voteRevealTx);
publishTx(voteRevealTx);
// TODO add comment...
// We don't want to wait for a successful broadcast to avoid issues if the broadcast succeeds delayed or at
// next startup but the tx was actually broadcasted.
myVoteListService.applyRevealTxId(myVote, voteRevealTx.getHashAsString());
// Just for additional resilience we republish our blind votes
final List<BlindVote> sortedBlindVoteListOfCycle = BlindVoteConsensus.getSortedBlindVoteListOfCycle(blindVoteListService);
rePublishBlindVotePayloadList(sortedBlindVoteListOfCycle);
} else {
final String msg = "Tx of stake out put is not in our cycle. That must not happen.";
log.error("{}. chainHeight={}, blindVoteTxId()={}", msg, chainHeight, myVote.getTxId());
voteRevealExceptions.add(new VoteRevealException(msg, stakeTxOutput.getTxId()));
}
}
Aggregations