use of bisq.core.dao.state.blockchain.TxOutput in project bisq-core by bisq-network.
the class VoteResultConsensus method getConnectedBlindVoteStakeOutput.
public static TxOutput getConnectedBlindVoteStakeOutput(Tx voteRevealTx, BsqStateService bsqStateService) throws VoteResultException {
try {
// We use the stake output of the blind vote tx as first input
final TxInput stakeTxInput = voteRevealTx.getTxInputs().get(0);
Optional<TxOutput> optionalBlindVoteStakeOutput = bsqStateService.getConnectedTxOutput(stakeTxInput);
checkArgument(optionalBlindVoteStakeOutput.isPresent(), "blindVoteStakeOutput must be present");
final TxOutput blindVoteStakeOutput = optionalBlindVoteStakeOutput.get();
checkArgument(blindVoteStakeOutput.getTxOutputType() == TxOutputType.BLIND_VOTE_LOCK_STAKE_OUTPUT, "blindVoteStakeOutput must be of type BLIND_VOTE_LOCK_STAKE_OUTPUT");
return blindVoteStakeOutput;
} catch (Throwable t) {
throw new VoteResultException(t);
}
}
use of bisq.core.dao.state.blockchain.TxOutput 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.state.blockchain.TxOutput in project bisq-core by bisq-network.
the class BsqStateService method isTxOutputSpendable.
public boolean isTxOutputSpendable(TxOutputKey key) {
if (!isUnspent(key))
return false;
Optional<TxOutput> optionalTxOutput = getUnspentTxOutput(key);
// The above isUnspent call satisfies optionalTxOutput.isPresent()
checkArgument(optionalTxOutput.isPresent(), "optionalTxOutput must be present");
TxOutput txOutput = optionalTxOutput.get();
switch(txOutput.getTxOutputType()) {
case UNDEFINED:
return false;
case GENESIS_OUTPUT:
case BSQ_OUTPUT:
return true;
case BTC_OUTPUT:
return false;
case PROPOSAL_OP_RETURN_OUTPUT:
case COMP_REQ_OP_RETURN_OUTPUT:
case ISSUANCE_CANDIDATE_OUTPUT:
return true;
case BLIND_VOTE_LOCK_STAKE_OUTPUT:
return false;
case BLIND_VOTE_OP_RETURN_OUTPUT:
case VOTE_REVEAL_UNLOCK_STAKE_OUTPUT:
case VOTE_REVEAL_OP_RETURN_OUTPUT:
return true;
case LOCKUP:
return false;
case LOCKUP_OP_RETURN_OUTPUT:
return true;
case UNLOCK:
return isLockTimeOverForUnlockTxOutput(txOutput);
case INVALID_OUTPUT:
return false;
default:
return false;
}
}
use of bisq.core.dao.state.blockchain.TxOutput in project bisq-core by bisq-network.
the class BsqWalletService method updateBsqBalance.
// /////////////////////////////////////////////////////////////////////////////////////////
// Balance
// /////////////////////////////////////////////////////////////////////////////////////////
private void updateBsqBalance() {
unverifiedBalance = Coin.valueOf(getTransactions(false).stream().filter(tx -> tx.getConfidence().getConfidenceType() == PENDING).mapToLong(tx -> {
// Sum up outputs into BSQ wallet and subtract the inputs using lockup or unlocking
// outputs since those inputs will be accounted for in lockupBondsBalance and
// unlockingBondsBalance
long outputs = tx.getOutputs().stream().filter(out -> out.isMine(wallet)).mapToLong(out -> out.getValue().value).sum();
// Account for spending of locked connectedOutputs
long lockedInputs = tx.getInputs().stream().filter(in -> {
TransactionOutput connectedOutput = in.getConnectedOutput();
if (connectedOutput != null) {
Transaction parentTransaction = connectedOutput.getParentTransaction();
// TODO SQ
if (parentTransaction != null) /* &&
parentTransaction.getConfidence().getConfidenceType() == BUILDING*/
{
TxOutputKey key = new TxOutputKey(parentTransaction.getHashAsString(), connectedOutput.getIndex());
return (connectedOutput.isMine(wallet) && (bsqStateService.isLockupOutput(key) || bsqStateService.isUnlockingOutput(key)));
}
}
return false;
}).mapToLong(in -> in != null ? in.getValue().value : 0).sum();
return outputs - lockedInputs;
}).sum());
Set<String> confirmedTxIdSet = getTransactions(false).stream().filter(tx -> tx.getConfidence().getConfidenceType() == BUILDING).map(Transaction::getHashAsString).collect(Collectors.toSet());
lockedForVotingBalance = Coin.valueOf(bsqStateService.getUnspentBlindVoteStakeTxOutputs().stream().filter(txOutput -> confirmedTxIdSet.contains(txOutput.getTxId())).mapToLong(TxOutput::getValue).sum());
lockupBondsBalance = Coin.valueOf(bsqStateService.getLockupTxOutputs().stream().filter(txOutput -> bsqStateService.isUnspent(txOutput.getKey())).filter(txOutput -> confirmedTxIdSet.contains(txOutput.getTxId())).mapToLong(TxOutput::getValue).sum());
unlockingBondsBalance = Coin.valueOf(bsqStateService.getUnspentUnlockingTxOutputsStream().filter(txOutput -> confirmedTxIdSet.contains(txOutput.getTxId())).mapToLong(TxOutput::getValue).sum());
availableBalance = bsqCoinSelector.select(NetworkParameters.MAX_MONEY, wallet.calculateAllSpendCandidates()).valueGathered;
if (availableBalance.isNegative())
availableBalance = Coin.ZERO;
availableNonBsqBalance = nonBsqCoinSelector.select(NetworkParameters.MAX_MONEY, wallet.calculateAllSpendCandidates()).valueGathered;
bsqBalanceListeners.forEach(e -> e.onUpdateBalances(availableBalance, availableNonBsqBalance, unverifiedBalance, lockedForVotingBalance, lockupBondsBalance, unlockingBondsBalance));
}
use of bisq.core.dao.state.blockchain.TxOutput in project bisq-core by bisq-network.
the class BsqWalletService method getValueSentFromMeForTransaction.
@Override
public Coin getValueSentFromMeForTransaction(Transaction transaction) throws ScriptException {
Coin result = Coin.ZERO;
// We check all our inputs and get the connected outputs.
for (int i = 0; i < transaction.getInputs().size(); i++) {
TransactionInput input = transaction.getInputs().get(i);
// We grab the connected output for that input
TransactionOutput connectedOutput = input.getConnectedOutput();
if (connectedOutput != null) {
// We grab the parent tx of the connected output
final Transaction parentTransaction = connectedOutput.getParentTransaction();
final boolean isConfirmed = parentTransaction != null && parentTransaction.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING;
if (connectedOutput.isMineOrWatched(wallet)) {
if (isConfirmed) {
// We lookup if we have a BSQ tx matching the parent tx
// We cannot make that findTx call outside of the loop as the parent tx can change at each iteration
Optional<Tx> txOptional = bsqStateService.getTx(parentTransaction.getHash().toString());
if (txOptional.isPresent()) {
TxOutput txOutput = txOptional.get().getTxOutputs().get(connectedOutput.getIndex());
if (bsqStateService.isBsqTxOutputType(txOutput)) {
// TODO check why values are not the same
if (txOutput.getValue() != connectedOutput.getValue().value)
log.warn("getValueSentToMeForTransaction: Value of BSQ output do not match BitcoinJ tx output. " + "txOutput.getValue()={}, output.getValue().value={}, txId={}", txOutput.getValue(), connectedOutput.getValue().value, txOptional.get().getId());
// If it is a valid BSQ output we add it
result = result.add(Coin.valueOf(txOutput.getValue()));
}
}
}
/*else {
// TODO atm we don't display amounts of unconfirmed txs but that might change so we leave that code
// if it will be required
// If the tx is not confirmed yet we add the value and assume it is a valid BSQ output.
result = result.add(connectedOutput.getValue());
}*/
}
}
}
return result;
}
Aggregations