use of bisq.core.btc.exceptions.TransactionVerificationException in project bisq-core by bisq-network.
the class DisputeManager method onDisputeResultMessage.
// We get that message at both peers. The dispute object is in context of the trader
private void onDisputeResultMessage(DisputeResultMessage disputeResultMessage) {
DisputeResult disputeResult = disputeResultMessage.getDisputeResult();
if (!isArbitrator(disputeResult)) {
final String tradeId = disputeResult.getTradeId();
Optional<Dispute> disputeOptional = findDispute(tradeId, disputeResult.getTraderId());
final String uid = disputeResultMessage.getUid();
if (disputeOptional.isPresent()) {
cleanupRetryMap(uid);
Dispute dispute = disputeOptional.get();
DisputeCommunicationMessage disputeCommunicationMessage = disputeResult.getDisputeCommunicationMessage();
if (!dispute.getDisputeCommunicationMessages().contains(disputeCommunicationMessage))
dispute.addDisputeMessage(disputeCommunicationMessage);
else
log.warn("We got a dispute mail msg what we have already stored. TradeId = " + disputeCommunicationMessage.getTradeId());
dispute.setIsClosed(true);
if (dispute.disputeResultProperty().get() != null)
log.warn("We got already a dispute result. That should only happen if a dispute needs to be closed " + "again because the first close did not succeed. TradeId = " + tradeId);
dispute.setDisputeResult(disputeResult);
// We need to avoid publishing the tx from both traders as it would create problems with zero confirmation withdrawals
// There would be different transactions if both sign and publish (signers: once buyer+arb, once seller+arb)
// The tx publisher is the winner or in case both get 50% the buyer, as the buyer has more inventive to publish the tx as he receives
// more BTC as he has deposited
final Contract contract = dispute.getContract();
boolean isBuyer = keyRing.getPubKeyRing().equals(contract.getBuyerPubKeyRing());
DisputeResult.Winner publisher = disputeResult.getWinner();
// Default isLoserPublisher is set to false
if (disputeResult.isLoserPublisher()) {
// we invert the logic
if (publisher == DisputeResult.Winner.BUYER)
publisher = DisputeResult.Winner.SELLER;
else if (publisher == DisputeResult.Winner.SELLER)
publisher = DisputeResult.Winner.BUYER;
}
if ((isBuyer && publisher == DisputeResult.Winner.BUYER) || (!isBuyer && publisher == DisputeResult.Winner.SELLER)) {
final Optional<Trade> tradeOptional = tradeManager.getTradeById(tradeId);
Transaction payoutTx = null;
if (tradeOptional.isPresent()) {
payoutTx = tradeOptional.get().getPayoutTx();
} else {
final Optional<Tradable> tradableOptional = closedTradableManager.getTradableById(tradeId);
if (tradableOptional.isPresent() && tradableOptional.get() instanceof Trade) {
payoutTx = ((Trade) tradableOptional.get()).getPayoutTx();
}
}
if (payoutTx == null) {
if (dispute.getDepositTxSerialized() != null) {
try {
log.debug("do payout Transaction ");
byte[] multiSigPubKey = isBuyer ? contract.getBuyerMultiSigPubKey() : contract.getSellerMultiSigPubKey();
DeterministicKey multiSigKeyPair = walletService.getMultiSigKeyPair(dispute.getTradeId(), multiSigPubKey);
Transaction signedDisputedPayoutTx = tradeWalletService.traderSignAndFinalizeDisputedPayoutTx(dispute.getDepositTxSerialized(), disputeResult.getArbitratorSignature(), disputeResult.getBuyerPayoutAmount(), disputeResult.getSellerPayoutAmount(), contract.getBuyerPayoutAddressString(), contract.getSellerPayoutAddressString(), multiSigKeyPair, contract.getBuyerMultiSigPubKey(), contract.getSellerMultiSigPubKey(), disputeResult.getArbitratorPubKey());
Transaction committedDisputedPayoutTx = tradeWalletService.addTxToWallet(signedDisputedPayoutTx);
log.debug("broadcast committedDisputedPayoutTx");
tradeWalletService.broadcastTx(committedDisputedPayoutTx, new FutureCallback<Transaction>() {
@Override
public void onSuccess(Transaction transaction) {
log.debug("BroadcastTx succeeded. Transaction:" + transaction);
// after successful publish we send peer the tx
dispute.setDisputePayoutTxId(transaction.getHashAsString());
sendPeerPublishedPayoutTxMessage(transaction, dispute, contract);
// set state after payout as we call swapTradeEntryToAvailableEntry
if (tradeManager.getTradeById(dispute.getTradeId()).isPresent())
tradeManager.closeDisputedTrade(dispute.getTradeId());
else {
Optional<OpenOffer> openOfferOptional = openOfferManager.getOpenOfferById(dispute.getTradeId());
if (openOfferOptional.isPresent())
openOfferManager.closeOpenOffer(openOfferOptional.get().getOffer());
}
}
@Override
public void onFailure(@NotNull Throwable t) {
log.error(t.getMessage());
}
}, 15);
} catch (AddressFormatException | WalletException | TransactionVerificationException e) {
e.printStackTrace();
log.error("Error at traderSignAndFinalizeDisputedPayoutTx " + e.getMessage());
throw new RuntimeException("Error at traderSignAndFinalizeDisputedPayoutTx " + e.toString());
}
} else {
log.warn("DepositTx is null. TradeId = " + tradeId);
}
} else {
log.warn("We got already a payout tx. That might be the case if the other peer did not get the " + "payout tx and opened a dispute. TradeId = " + tradeId);
dispute.setDisputePayoutTxId(payoutTx.getHashAsString());
sendPeerPublishedPayoutTxMessage(payoutTx, dispute, contract);
}
} else {
log.trace("We don't publish the tx as we are not the winning party.");
// Clean up tangling trades
if (dispute.disputeResultProperty().get() != null && dispute.isClosed() && tradeManager.getTradeById(dispute.getTradeId()).isPresent())
tradeManager.closeDisputedTrade(dispute.getTradeId());
}
} else {
log.debug("We got a dispute result msg but we don't have a matching dispute. " + "That might happen when we get the disputeResultMessage before the dispute was created. " + "We try again after 2 sec. to apply the disputeResultMessage. TradeId = " + tradeId);
if (!delayMsgMap.containsKey(uid)) {
// We delay2 sec. to be sure the comm. msg gets added first
Timer timer = UserThread.runAfter(() -> onDisputeResultMessage(disputeResultMessage), 2);
delayMsgMap.put(uid, timer);
} else {
log.warn("We got a dispute result msg after we already repeated to apply the message after a delay. " + "That should never happen. TradeId = " + tradeId);
}
}
} else {
log.error("Arbitrator received disputeResultMessage. That must never happen.");
}
}
use of bisq.core.btc.exceptions.TransactionVerificationException in project bisq-core by bisq-network.
the class WalletService method verifyTransaction.
public static void verifyTransaction(Transaction transaction) throws TransactionVerificationException {
try {
log.trace("Verify transaction " + transaction);
transaction.verify();
} catch (Throwable t) {
t.printStackTrace();
log.error(t.getMessage());
throw new TransactionVerificationException(t);
}
}
use of bisq.core.btc.exceptions.TransactionVerificationException in project bisq-core by bisq-network.
the class VoteService method revealVote.
private void revealVote(MyVote myVote) {
byte[] hashOfBlindVoteList = VoteConsensus.getHashOfBlindVoteList(blindVoteSortedList);
log.info("Sha256Ripemd160 hash of hashOfBlindVoteList " + Utilities.bytesAsHexString(hashOfBlindVoteList));
byte[] opReturnData = VoteConsensus.getOpReturnDataForVoteReveal(hashOfBlindVoteList, myVote.getSecretKey());
final Set<TxOutput> lockedForVoteTxOutputs = readableBsqBlockChain.getLockedForVoteTxOutputs();
Optional<TxOutput> optionalStakeTxOutput = lockedForVoteTxOutputs.stream().filter(txOutput -> txOutput.getTxId().equals(myVote.getTxId())).findAny();
if (optionalStakeTxOutput.isPresent()) {
try {
final TxOutput stakeTxOutput = optionalStakeTxOutput.get();
VoteConsensus.unlockStakeTxOutputType(stakeTxOutput);
Transaction voteRevealTx = getVoteRevealTx(stakeTxOutput, opReturnData);
myVote.setRevealTxId(voteRevealTx.getHashAsString());
myVoteListStorage.queueUpForSave();
publishRevealTx(voteRevealTx, new FutureCallback<Transaction>() {
@Override
public void onSuccess(@Nullable Transaction result) {
}
@Override
public void onFailure(@NotNull Throwable t) {
}
});
} catch (InsufficientMoneyException e) {
e.printStackTrace();
} catch (WalletException e) {
e.printStackTrace();
} catch (TransactionVerificationException e) {
e.printStackTrace();
}
} else {
// log.warn("optionalStakeTxOutput is not present. myVote={}", myVote);
}
}
use of bisq.core.btc.exceptions.TransactionVerificationException in project bisq-desktop by bisq-network.
the class ActiveProposalsView method activate.
@Override
protected void activate() {
super.activate();
bsqWalletService.addBsqBalanceListener(this);
onUpdateBalances(bsqWalletService.getAvailableBalance(), bsqWalletService.getPendingBalance(), bsqWalletService.getLockedForVotingBalance(), bsqWalletService.getLockedInBondsBalance());
if (voteButton != null) {
voteButton.setOnAction(e -> {
Coin stake = bsqFormatter.parseToCoin(stakeInputTextField.getText());
// TODO show popup
try {
voteService.publishBlindVote(stake, new FutureCallback<Transaction>() {
@Override
public void onSuccess(@Nullable Transaction result) {
// TODO
}
@Override
public void onFailure(@NotNull Throwable t) {
// TODO
}
});
} catch (CryptoException e1) {
// TODO show error popup
e1.printStackTrace();
} catch (InsufficientBsqException e1) {
e1.printStackTrace();
} catch (WalletException e1) {
e1.printStackTrace();
} catch (TransactionVerificationException e1) {
e1.printStackTrace();
} catch (InsufficientMoneyException e1) {
e1.printStackTrace();
} catch (ChangeBelowDustException e1) {
e1.printStackTrace();
} catch (InvalidProtocolBufferException e1) {
e1.printStackTrace();
}
});
}
}
use of bisq.core.btc.exceptions.TransactionVerificationException in project bisq-desktop by bisq-network.
the class ManualPayoutTxWindow method addContent.
private void addContent() {
// We dont translate here as it is for dev only purpose
InputTextField depositTxHex = addLabelInputTextField(gridPane, ++rowIndex, "depositTxHex:").second;
InputTextField buyerPayoutAmount = addLabelInputTextField(gridPane, ++rowIndex, "buyerPayoutAmount:").second;
InputTextField sellerPayoutAmount = addLabelInputTextField(gridPane, ++rowIndex, "sellerPayoutAmount:").second;
InputTextField arbitratorPayoutAmount = addLabelInputTextField(gridPane, ++rowIndex, "arbitratorPayoutAmount:").second;
InputTextField txFee = addLabelInputTextField(gridPane, ++rowIndex, "Tx fee:").second;
InputTextField buyerAddressString = addLabelInputTextField(gridPane, ++rowIndex, "buyerAddressString:").second;
InputTextField sellerAddressString = addLabelInputTextField(gridPane, ++rowIndex, "sellerAddressString:").second;
InputTextField arbitratorAddressString = addLabelInputTextField(gridPane, ++rowIndex, "arbitratorAddressString:").second;
InputTextField buyerPrivateKeyAsHex = addLabelInputTextField(gridPane, ++rowIndex, "buyerPrivateKeyAsHex:").second;
InputTextField sellerPrivateKeyAsHex = addLabelInputTextField(gridPane, ++rowIndex, "sellerPrivateKeyAsHex:").second;
InputTextField arbitratorPrivateKeyAsHex = addLabelInputTextField(gridPane, ++rowIndex, "arbitratorPrivateKeyAsHex:").second;
InputTextField buyerPubKeyAsHex = addLabelInputTextField(gridPane, ++rowIndex, "buyerPubKeyAsHex:").second;
InputTextField sellerPubKeyAsHex = addLabelInputTextField(gridPane, ++rowIndex, "sellerPubKeyAsHex:").second;
InputTextField arbitratorPubKeyAsHex = addLabelInputTextField(gridPane, ++rowIndex, "arbitratorPubKeyAsHex:").second;
InputTextField P2SHMultiSigOutputScript = addLabelInputTextField(gridPane, ++rowIndex, "P2SHMultiSigOutputScript:").second;
// Notes:
// Open with alt+g and enable DEV mode
// Priv key is only visible if pw protection is removed (wallet details data (alt+j))
// Take P2SHMultiSigOutputScript from depositTx in blockexplorer
// Take missing buyerPubKeyAsHex and sellerPubKeyAsHex from contract data!
// Lookup sellerPrivateKeyAsHex associated with sellerPubKeyAsHex (or buyers) in wallet details data
// sellerPubKeys/buyerPubKeys are auto generated if used the fields below
// Never set the priv arbitr. key here!
depositTxHex.setText("");
P2SHMultiSigOutputScript.setText("");
buyerPayoutAmount.setText("");
sellerPayoutAmount.setText("");
arbitratorPayoutAmount.setText("0");
buyerAddressString.setText("");
buyerPubKeyAsHex.setText("");
buyerPrivateKeyAsHex.setText("");
sellerAddressString.setText("");
sellerPubKeyAsHex.setText("");
sellerPrivateKeyAsHex.setText("");
arbitratorAddressString.setText("");
arbitratorPubKeyAsHex.setText("");
actionButtonText("Sign and publish transaction");
FutureCallback<Transaction> callback = new FutureCallback<Transaction>() {
@Override
public void onSuccess(@Nullable Transaction result) {
log.error("onSuccess");
UserThread.execute(() -> {
String txId = result != null ? result.getHashAsString() : "null";
new Popup<>().information("Transaction successful published. Transaction ID: " + txId).show();
});
}
@Override
public void onFailure(@NotNull Throwable t) {
log.error(t.toString());
log.error("onFailure");
UserThread.execute(() -> new Popup<>().warning(t.toString()).show());
}
};
onAction(() -> {
if (GUIUtil.isReadyForTxBroadcast(p2PService, walletsSetup)) {
try {
tradeWalletService.emergencySignAndPublishPayoutTx(depositTxHex.getText(), Coin.parseCoin(buyerPayoutAmount.getText()), Coin.parseCoin(sellerPayoutAmount.getText()), Coin.parseCoin(arbitratorPayoutAmount.getText()), Coin.parseCoin(txFee.getText()), buyerAddressString.getText(), sellerAddressString.getText(), arbitratorAddressString.getText(), buyerPrivateKeyAsHex.getText(), sellerPrivateKeyAsHex.getText(), arbitratorPrivateKeyAsHex.getText(), buyerPubKeyAsHex.getText(), sellerPubKeyAsHex.getText(), arbitratorPubKeyAsHex.getText(), P2SHMultiSigOutputScript.getText(), callback);
} catch (AddressFormatException | WalletException | TransactionVerificationException e) {
log.error(e.toString());
e.printStackTrace();
UserThread.execute(() -> new Popup<>().warning(e.toString()).show());
}
} else {
GUIUtil.showNotReadyForTxBroadcastPopups(p2PService, walletsSetup);
}
});
}
Aggregations