Search in sources :

Example 1 with AckMessage

use of bisq.network.p2p.AckMessage in project bisq-core by bisq-network.

the class OpenOfferManager method sendAckMessage.

private void sendAckMessage(OfferAvailabilityRequest message, NodeAddress sender, boolean result, String errorMessage) {
    String offerId = message.getOfferId();
    String sourceUid = message.getUid();
    AckMessage ackMessage = new AckMessage(p2PService.getNetworkNode().getNodeAddress(), AckMessageSourceType.OFFER_MESSAGE, message.getClass().getSimpleName(), sourceUid, offerId, result, errorMessage);
    final NodeAddress takersNodeAddress = sender;
    PubKeyRing takersPubKeyRing = message.getPubKeyRing();
    log.info("Send AckMessage for OfferAvailabilityRequest to peer {} with offerId {} and sourceUid {}", takersNodeAddress, offerId, ackMessage.getSourceUid());
    p2PService.sendEncryptedDirectMessage(takersNodeAddress, takersPubKeyRing, ackMessage, new SendDirectMessageListener() {

        @Override
        public void onArrived() {
            log.info("AckMessage for OfferAvailabilityRequest arrived at takersNodeAddress {}. offerId={}, sourceUid={}", takersNodeAddress, offerId, ackMessage.getSourceUid());
        }

        @Override
        public void onFault(String errorMessage) {
            log.error("AckMessage for OfferAvailabilityRequest failed. AckMessage={}, takersNodeAddress={}, errorMessage={}", ackMessage, takersNodeAddress, errorMessage);
        }
    });
}
Also used : AckMessage(bisq.network.p2p.AckMessage) PubKeyRing(bisq.common.crypto.PubKeyRing) NodeAddress(bisq.network.p2p.NodeAddress) SendDirectMessageListener(bisq.network.p2p.SendDirectMessageListener)

Example 2 with AckMessage

use of bisq.network.p2p.AckMessage in project bisq-core by bisq-network.

the class OfferAvailabilityProtocol method sendAckMessage.

private void sendAckMessage(OfferAvailabilityResponse message, boolean result, @Nullable String errorMessage) {
    String offerId = message.getOfferId();
    String sourceUid = message.getUid();
    final NodeAddress makersNodeAddress = model.getPeerNodeAddress();
    PubKeyRing makersPubKeyRing = model.getOffer().getPubKeyRing();
    log.info("Send AckMessage for OfferAvailabilityResponse to peer {} with offerId {} and sourceUid {}", makersNodeAddress, offerId, sourceUid);
    AckMessage ackMessage = new AckMessage(model.getP2PService().getNetworkNode().getNodeAddress(), AckMessageSourceType.OFFER_MESSAGE, message.getClass().getSimpleName(), sourceUid, offerId, result, errorMessage);
    model.getP2PService().sendEncryptedDirectMessage(makersNodeAddress, makersPubKeyRing, ackMessage, new SendDirectMessageListener() {

        @Override
        public void onArrived() {
            log.info("AckMessage for OfferAvailabilityResponse arrived at makersNodeAddress {}. " + "offerId={}, sourceUid={}", makersNodeAddress, offerId, ackMessage.getSourceUid());
        }

        @Override
        public void onFault(String errorMessage) {
            log.error("AckMessage for OfferAvailabilityResponse failed. AckMessage={}, " + "makersNodeAddress={}, errorMessage={}", ackMessage, makersNodeAddress, errorMessage);
        }
    });
}
Also used : AckMessage(bisq.network.p2p.AckMessage) PubKeyRing(bisq.common.crypto.PubKeyRing) NodeAddress(bisq.network.p2p.NodeAddress) SendDirectMessageListener(bisq.network.p2p.SendDirectMessageListener)

Example 3 with AckMessage

use of bisq.network.p2p.AckMessage in project bisq-core by bisq-network.

the class DisputeManager method applyMessages.

private void applyMessages() {
    decryptedDirectMessageWithPubKeys.forEach(decryptedMessageWithPubKey -> {
        NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope();
        if (networkEnvelope instanceof DisputeMessage) {
            dispatchMessage((DisputeMessage) networkEnvelope);
        } else if (networkEnvelope instanceof AckMessage) {
            processAckMessage((AckMessage) networkEnvelope, null);
        }
    });
    decryptedDirectMessageWithPubKeys.clear();
    decryptedMailboxMessageWithPubKeys.forEach(decryptedMessageWithPubKey -> {
        NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope();
        log.debug("decryptedMessageWithPubKey.message " + networkEnvelope);
        if (networkEnvelope instanceof DisputeMessage) {
            dispatchMessage((DisputeMessage) networkEnvelope);
            p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey);
        } else if (networkEnvelope instanceof AckMessage) {
            processAckMessage((AckMessage) networkEnvelope, decryptedMessageWithPubKey);
        }
    });
    decryptedMailboxMessageWithPubKeys.clear();
}
Also used : DisputeMessage(bisq.core.arbitration.messages.DisputeMessage) OpenNewDisputeMessage(bisq.core.arbitration.messages.OpenNewDisputeMessage) PeerOpenedDisputeMessage(bisq.core.arbitration.messages.PeerOpenedDisputeMessage) AckMessage(bisq.network.p2p.AckMessage) NetworkEnvelope(bisq.common.proto.network.NetworkEnvelope)

Example 4 with AckMessage

use of bisq.network.p2p.AckMessage in project bisq-core by bisq-network.

the class DisputeManager method sendAckMessage.

private void sendAckMessage(DisputeMessage disputeMessage, PubKeyRing peersPubKeyRing, boolean result, @Nullable String errorMessage) {
    String tradeId = disputeMessage.getTradeId();
    String uid = disputeMessage.getUid();
    AckMessage ackMessage = new AckMessage(p2PService.getNetworkNode().getNodeAddress(), AckMessageSourceType.DISPUTE_MESSAGE, disputeMessage.getClass().getSimpleName(), uid, tradeId, result, errorMessage);
    final NodeAddress peersNodeAddress = disputeMessage.getSenderNodeAddress();
    log.info("Send AckMessage for {} to peer {}. tradeId={}, uid={}", ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, uid);
    p2PService.sendEncryptedMailboxMessage(peersNodeAddress, peersPubKeyRing, ackMessage, new SendMailboxMessageListener() {

        @Override
        public void onArrived() {
            log.info("AckMessage for {} arrived at peer {}. tradeId={}, uid={}", ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, uid);
        }

        @Override
        public void onStoredInMailbox() {
            log.info("AckMessage for {} stored in mailbox for peer {}. tradeId={}, uid={}", ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, uid);
        }

        @Override
        public void onFault(String errorMessage) {
            log.error("AckMessage for {} failed. Peer {}. tradeId={}, uid={}, errorMessage={}", ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, uid, errorMessage);
        }
    });
}
Also used : AckMessage(bisq.network.p2p.AckMessage) NodeAddress(bisq.network.p2p.NodeAddress) SendMailboxMessageListener(bisq.network.p2p.SendMailboxMessageListener)

Example 5 with AckMessage

use of bisq.network.p2p.AckMessage 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) {
    String errorMessage = null;
    boolean success = false;
    PubKeyRing arbitratorsPubKeyRing = null;
    DisputeResult disputeResult = disputeResultMessage.getDisputeResult();
    if (isArbitrator(disputeResult)) {
        log.error("Arbitrator received disputeResultMessage. That must never happen.");
        return;
    }
    final String tradeId = disputeResult.getTradeId();
    Optional<Dispute> disputeOptional = findDispute(tradeId, disputeResult.getTraderId());
    final String uid = disputeResultMessage.getUid();
    if (!disputeOptional.isPresent()) {
        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);
        }
        return;
    }
    try {
        cleanupRetryMap(uid);
        Dispute dispute = disputeOptional.get();
        arbitratorsPubKeyRing = dispute.getArbitratorPubKeyRing();
        DisputeCommunicationMessage disputeCommunicationMessage = disputeResult.getDisputeCommunicationMessage();
        if (!dispute.getDisputeCommunicationMessages().contains(disputeCommunicationMessage))
            dispute.addDisputeCommunicationMessage(disputeCommunicationMessage);
        else if (disputeCommunicationMessage != null)
            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) {
                    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);
                    tradeWalletService.broadcastTx(committedDisputedPayoutTx, new TxBroadcaster.Callback() {

                        @Override
                        public void onSuccess(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());
                                openOfferOptional.ifPresent(openOffer -> openOfferManager.closeOpenOffer(openOffer.getOffer()));
                            }
                        }

                        @Override
                        public void onFailure(TxBroadcastException exception) {
                            log.error(exception.getMessage());
                        }
                    }, 15);
                    success = true;
                } else {
                    errorMessage = "DepositTx is null. TradeId = " + tradeId;
                    log.warn(errorMessage);
                    success = false;
                }
            } 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);
                success = true;
            }
        } 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());
            }
            success = true;
        }
    } catch (AddressFormatException | WalletException | TransactionVerificationException e) {
        e.printStackTrace();
        errorMessage = "Error at traderSignAndFinalizeDisputedPayoutTx " + e.toString();
        log.error(errorMessage);
        success = false;
        throw new RuntimeException(errorMessage);
    } finally {
        if (arbitratorsPubKeyRing != null) {
            // We use the disputeCommunicationMessage as we only persist those not the disputeResultMessage.
            // If we would use the disputeResultMessage we could not lookup for the msg when we receive the AckMessage.
            DisputeCommunicationMessage disputeCommunicationMessage = disputeResultMessage.getDisputeResult().getDisputeCommunicationMessage();
            sendAckMessage(disputeCommunicationMessage, arbitratorsPubKeyRing, success, errorMessage);
        }
    }
}
Also used : DisputeMessage(bisq.core.arbitration.messages.DisputeMessage) PubKeyRing(bisq.common.crypto.PubKeyRing) Arrays(java.util.Arrays) Transaction(org.bitcoinj.core.Transaction) OpenOffer(bisq.core.offer.OpenOffer) AckMessageSourceType(bisq.network.p2p.AckMessageSourceType) Inject(com.google.inject.Inject) LoggerFactory(org.slf4j.LoggerFactory) Contract(bisq.core.trade.Contract) ListChangeListener(javafx.collections.ListChangeListener) Res(bisq.core.locale.Res) BootstrapListener(bisq.network.p2p.BootstrapListener) SimpleIntegerProperty(javafx.beans.property.SimpleIntegerProperty) Map(java.util.Map) DeterministicKey(org.bitcoinj.crypto.DeterministicKey) AddressFormatException(org.bitcoinj.core.AddressFormatException) WalletException(bisq.core.btc.exceptions.WalletException) TxBroadcastException(bisq.core.btc.wallet.TxBroadcastException) ClosedTradableManager(bisq.core.trade.closed.ClosedTradableManager) NetworkEnvelope(bisq.common.proto.network.NetworkEnvelope) P2PService(bisq.network.p2p.P2PService) PersistedDataHost(bisq.common.proto.persistable.PersistedDataHost) Subscription(org.fxmisc.easybind.Subscription) UUID(java.util.UUID) CopyOnWriteArraySet(java.util.concurrent.CopyOnWriteArraySet) Collectors(java.util.stream.Collectors) AckMessage(bisq.network.p2p.AckMessage) OpenNewDisputeMessage(bisq.core.arbitration.messages.OpenNewDisputeMessage) List(java.util.List) DisputeResultMessage(bisq.core.arbitration.messages.DisputeResultMessage) Stream(java.util.stream.Stream) TradeWalletService(bisq.core.btc.wallet.TradeWalletService) WalletsSetup(bisq.core.btc.wallet.WalletsSetup) TradeManager(bisq.core.trade.TradeManager) NodeAddress(bisq.network.p2p.NodeAddress) UserThread(bisq.common.UserThread) Optional(java.util.Optional) ObservableList(javafx.collections.ObservableList) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) Getter(lombok.Getter) Timer(bisq.common.Timer) HashMap(java.util.HashMap) Tradable(bisq.core.trade.Tradable) TxBroadcaster(bisq.core.btc.wallet.TxBroadcaster) IntegerProperty(javafx.beans.property.IntegerProperty) PersistenceProtoResolver(bisq.common.proto.persistable.PersistenceProtoResolver) ArrayList(java.util.ArrayList) Tuple2(bisq.common.util.Tuple2) TransactionVerificationException(bisq.core.btc.exceptions.TransactionVerificationException) Named(javax.inject.Named) Nullable(javax.annotation.Nullable) PeerOpenedDisputeMessage(bisq.core.arbitration.messages.PeerOpenedDisputeMessage) PeerPublishedDisputePayoutTxMessage(bisq.core.arbitration.messages.PeerPublishedDisputePayoutTxMessage) Logger(org.slf4j.Logger) Trade(bisq.core.trade.Trade) FaultHandler(bisq.common.handlers.FaultHandler) ResultHandler(bisq.common.handlers.ResultHandler) OpenOfferManager(bisq.core.offer.OpenOfferManager) SendMailboxMessageListener(bisq.network.p2p.SendMailboxMessageListener) File(java.io.File) DisputeCommunicationMessage(bisq.core.arbitration.messages.DisputeCommunicationMessage) EasyBind(org.fxmisc.easybind.EasyBind) Storage(bisq.common.storage.Storage) KeyRing(bisq.common.crypto.KeyRing) DecryptedMessageWithPubKey(bisq.network.p2p.DecryptedMessageWithPubKey) Tradable(bisq.core.trade.Tradable) Trade(bisq.core.trade.Trade) PubKeyRing(bisq.common.crypto.PubKeyRing) DisputeCommunicationMessage(bisq.core.arbitration.messages.DisputeCommunicationMessage) WalletException(bisq.core.btc.exceptions.WalletException) AddressFormatException(org.bitcoinj.core.AddressFormatException) Optional(java.util.Optional) TransactionVerificationException(bisq.core.btc.exceptions.TransactionVerificationException) TxBroadcastException(bisq.core.btc.wallet.TxBroadcastException) TxBroadcaster(bisq.core.btc.wallet.TxBroadcaster) Timer(bisq.common.Timer) Transaction(org.bitcoinj.core.Transaction) Contract(bisq.core.trade.Contract) DeterministicKey(org.bitcoinj.crypto.DeterministicKey)

Aggregations

AckMessage (bisq.network.p2p.AckMessage)6 NodeAddress (bisq.network.p2p.NodeAddress)5 PubKeyRing (bisq.common.crypto.PubKeyRing)3 SendMailboxMessageListener (bisq.network.p2p.SendMailboxMessageListener)3 NetworkEnvelope (bisq.common.proto.network.NetworkEnvelope)2 DisputeMessage (bisq.core.arbitration.messages.DisputeMessage)2 OpenNewDisputeMessage (bisq.core.arbitration.messages.OpenNewDisputeMessage)2 PeerOpenedDisputeMessage (bisq.core.arbitration.messages.PeerOpenedDisputeMessage)2 SendDirectMessageListener (bisq.network.p2p.SendDirectMessageListener)2 Timer (bisq.common.Timer)1 UserThread (bisq.common.UserThread)1 KeyRing (bisq.common.crypto.KeyRing)1 FaultHandler (bisq.common.handlers.FaultHandler)1 ResultHandler (bisq.common.handlers.ResultHandler)1 PersistedDataHost (bisq.common.proto.persistable.PersistedDataHost)1 PersistenceProtoResolver (bisq.common.proto.persistable.PersistenceProtoResolver)1 Storage (bisq.common.storage.Storage)1 Tuple2 (bisq.common.util.Tuple2)1 DisputeCommunicationMessage (bisq.core.arbitration.messages.DisputeCommunicationMessage)1 DisputeResultMessage (bisq.core.arbitration.messages.DisputeResultMessage)1