From 5afd2bde110434c43ddbb52f33941ed10604e3a5 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Wed, 15 Mar 2017 17:06:44 -0500 Subject: [PATCH] Separate security deposit for buyer and seller. Remove arbitrator amount and address at dispute result. Remove Payout policy. Add bank as reason. --- common/src/main/java/io/bisq/app/DevEnv.java | 2 +- common/src/main/proto/bsmessage.proto | 37 +-- .../resources/i18n/displayStrings.properties | 16 +- .../i18n/displayStrings_de.properties | 15 +- .../io/bisq/arbitration/DisputeManager.java | 13 +- .../bisq/btc/wallet/TradeWalletService.java | 17 +- .../protocol/trade/BuyerAsTakerProtocol.java | 2 +- ...ffererCreatesAndSignsDepositTxAsBuyer.java | 2 +- ...fererCreatesAndSignsDepositTxAsSeller.java | 2 +- .../SignAndPublishDepositTxAsBuyer.java} | 10 +- .../SignAndPublishDepositTxAsSeller.java | 4 +- .../windows/DisputeSummaryWindow.java | 314 ++++++------------ .../messages/arbitration/DisputeResult.java | 66 +--- .../messages/trade/offer/payload/Offer.java | 4 +- .../p2p/network/ProtoBufferUtilities.java | 6 +- 15 files changed, 153 insertions(+), 357 deletions(-) rename core/src/main/java/io/bisq/trade/protocol/trade/tasks/{buyer/TakerSignAndPublishDepositTxAsBuyer.java => taker/SignAndPublishDepositTxAsBuyer.java} (92%) rename core/src/main/java/io/bisq/trade/protocol/trade/tasks/{seller => taker}/SignAndPublishDepositTxAsSeller.java (97%) diff --git a/common/src/main/java/io/bisq/app/DevEnv.java b/common/src/main/java/io/bisq/app/DevEnv.java index 9d7a4787d5..ae9c3c395c 100644 --- a/common/src/main/java/io/bisq/app/DevEnv.java +++ b/common/src/main/java/io/bisq/app/DevEnv.java @@ -17,5 +17,5 @@ public class DevEnv { // If set to true we ignore several UI behavior like confirmation popups as well dummy accounts are created and // offers are filled with default values. Intended to make dev testing faster. - public static final boolean DEV_MODE = STRESS_TEST_MODE || false; + public static final boolean DEV_MODE = STRESS_TEST_MODE || true; } diff --git a/common/src/main/proto/bsmessage.proto b/common/src/main/proto/bsmessage.proto index c675b46150..ddeffde0d2 100644 --- a/common/src/main/proto/bsmessage.proto +++ b/common/src/main/proto/bsmessage.proto @@ -385,16 +385,9 @@ message DisputeResultMessage { // payload message DisputeResult { - enum DisputeFeePolicy { - LOSER = 0; - SPLIT = 1; - WAIVE = 2; - } - enum Winner { BUYER = 0; SELLER = 1; - STALE_MATE = 2; } // only append new values as we use the ordinal value @@ -405,27 +398,25 @@ message DisputeResult { SCAM = 3; PROTOCOL_VIOLATION = 4; NO_REPLY = 5; + BANK_PROBLEMS = 6; } string trade_id = 1; int32 trader_id = 2; - DisputeFeePolicy dispute_fee_policy = 3; - Winner winner = 4; - int32 reason_ordinal = 5; + Winner winner = 3; + int32 reason_ordinal = 4; - bool tamper_proof_evidence = 6; - bool id_verification = 7; - bool screen_cast = 8; - string summary_notes = 9; - DisputeCommunicationMessage dispute_communication_message = 10; - bytes arbitrator_signature = 11; - int64 buyer_payout_amount = 12; - int64 seller_payout_amount = 13; - int64 arbitrator_payout_amount = 14; - string arbitrator_address_as_string = 15; - bytes arbitrator_pub_key = 16; - int64 close_date = 17; - bool is_loser_publisher = 18; + bool tamper_proof_evidence = 5; + bool id_verification = 6; + bool screen_cast = 7; + string summary_notes = 8; + DisputeCommunicationMessage dispute_communication_message = 9; + bytes arbitrator_signature = 10; + int64 buyer_payout_amount = 11; + int64 seller_payout_amount = 12; + bytes arbitrator_pub_key = 13; + int64 close_date = 14; + bool is_loser_publisher = 15; } message OpenNewDisputeMessage { Dispute dispute = 1; diff --git a/common/src/main/resources/i18n/displayStrings.properties b/common/src/main/resources/i18n/displayStrings.properties index 864d3a625b..56ea7bec18 100644 --- a/common/src/main/resources/i18n/displayStrings.properties +++ b/common/src/main/resources/i18n/displayStrings.properties @@ -976,19 +976,13 @@ disputeSummaryWindow.evidence.tamperProof=Tamper proof evidence disputeSummaryWindow.evidence.id=ID Verification disputeSummaryWindow.evidence.video=Video/Screencast disputeSummaryWindow.payout=Trade amount payout: -disputeSummaryWindow.payout.buyerWinner=BTC buyer gets trade amount payout -disputeSummaryWindow.payout.sellerWinner=BTC seller gets trade amount payout -disputeSummaryWindow.payout.both=Both gets half trade amount payout +disputeSummaryWindow.payout.getsTradeAmount=BTC {0} gets trade amount payout +disputeSummaryWindow.payout.getsAll=BTC {0} gets all disputeSummaryWindow.payout.custom=Custom payout disputeSummaryWindow.payout.adjustAmount=Amount entered exceeds available amount of {0}.\n\ We adjust this input field to the max possible value. -disputeSummaryWindow.arbitrationFee=Arbitration fee: -disputeSummaryWindow.arbitrationFee.looserPay=Loser pays arbitration fee -disputeSummaryWindow.split=Split arbitration fee -disputeSummaryWindow.arbitrationFee.waive=Waive arbitration fee disputeSummaryWindow.payoutAmount.buyer=Buyer's payout amount: disputeSummaryWindow.payoutAmount.seller=Seller's payout amount: -disputeSummaryWindow.payoutAmount.arbitrator=Arbitrator's payout amount: disputeSummaryWindow.payoutAmount.invert=Use loser as publisher: disputeSummaryWindow.reason=Reason of dispute: disputeSummaryWindow.reason.bug=Bug @@ -997,6 +991,7 @@ disputeSummaryWindow.reason.protocolViolation=Protocol violation disputeSummaryWindow.reason.noReply=No reply disputeSummaryWindow.reason.scam=Scam disputeSummaryWindow.reason.other=Other +disputeSummaryWindow.reason.bank=Bank disputeSummaryWindow.summaryNotes=Summary notes: disputeSummaryWindow.addSummaryNotes=Add summary notes disputeSummaryWindow.close.button=Close ticket @@ -1006,9 +1001,8 @@ Summary:\n\ {3} did ID verification: {4}\n\ {5} did screencast or video: {6}\n\ Payout amount for BTC buyer: {7}\n\ -Payout amount for BTC seller: {8}\n\ -Arbitrator''s dispute fee: {9}\n\n\ -Summary notes:\n{10} +Payout amount for BTC seller: {8}\n\n\ +Summary notes:\n{9} disputeSummaryWindow.close.closePeer=You need to close also the trading peers ticket! emptyWalletWindow.headline=Emergency wallet tool diff --git a/common/src/main/resources/i18n/displayStrings_de.properties b/common/src/main/resources/i18n/displayStrings_de.properties index 5cad38b747..889843f400 100644 --- a/common/src/main/resources/i18n/displayStrings_de.properties +++ b/common/src/main/resources/i18n/displayStrings_de.properties @@ -976,19 +976,13 @@ disputeSummaryWindow.evidence.tamperProof=Tamper proof evidence disputeSummaryWindow.evidence.id=ID Verification disputeSummaryWindow.evidence.video=Video/Screencast disputeSummaryWindow.payout=Trade amount payout: -disputeSummaryWindow.payout.buyerWinner=BTC buyer gets trade amount payout -disputeSummaryWindow.payout.sellerWinner=BTC seller gets trade amount payout -disputeSummaryWindow.payout.both=Both gets half trade amount payout +disputeSummaryWindow.payout.getsTradeAmount=BTC {0} gets trade amount payout +disputeSummaryWindow.payout.getsAll=BTC {0} gets all disputeSummaryWindow.payout.custom=Custom payout disputeSummaryWindow.payout.adjustAmount=Amount entered exceeds available amount of {0}.\n\ We adjust this input field to the max possible value. -disputeSummaryWindow.arbitrationFee=Arbitration fee: -disputeSummaryWindow.arbitrationFee.looserPay=Loser pays arbitration fee -disputeSummaryWindow.split=Split arbitration fee -disputeSummaryWindow.arbitrationFee.waive=Waive arbitration fee disputeSummaryWindow.payoutAmount.buyer=Buyer's payout amount: disputeSummaryWindow.payoutAmount.seller=Seller's payout amount: -disputeSummaryWindow.payoutAmount.arbitrator=Arbitrator's payout amount: disputeSummaryWindow.payoutAmount.invert=Use loser as publisher: disputeSummaryWindow.reason=Reason of dispute: disputeSummaryWindow.reason.bug=Bug @@ -1006,9 +1000,8 @@ Summary:\n\ {3} did ID verification: {4}\n\ {5} did screencast or video: {6}\n\ Payout amount for BTC buyer: {7}\n\ -Payout amount for BTC seller: {8}\n\ -Arbitrator''s dispute fee: {9}\n\n\ -Summary notes:\n{10} +Payout amount for BTC seller: {8}\n\n\ +Summary notes:\n{9} disputeSummaryWindow.close.closePeer=You need to close also the trading peers ticket! emptyWalletWindow.headline=Emergency wallet tool diff --git a/core/src/main/java/io/bisq/arbitration/DisputeManager.java b/core/src/main/java/io/bisq/arbitration/DisputeManager.java index dd66720b6d..46b1bbe83e 100644 --- a/core/src/main/java/io/bisq/arbitration/DisputeManager.java +++ b/core/src/main/java/io/bisq/arbitration/DisputeManager.java @@ -59,10 +59,7 @@ import org.slf4j.LoggerFactory; import javax.inject.Named; import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.CopyOnWriteArraySet; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -580,8 +577,7 @@ public class DisputeManager { } if ((isBuyer && publisher == DisputeResult.Winner.BUYER) - || (!isBuyer && publisher == DisputeResult.Winner.SELLER) - || (isBuyer && publisher == DisputeResult.Winner.STALE_MATE)) { + || (!isBuyer && publisher == DisputeResult.Winner.SELLER)) { final Optional tradeOptional = tradeManager.getTradeById(tradeId); Transaction payoutTx = null; @@ -605,10 +601,8 @@ public class DisputeManager { disputeResult.getArbitratorSignature(), disputeResult.getBuyerPayoutAmount(), disputeResult.getSellerPayoutAmount(), - disputeResult.getArbitratorPayoutAmount(), contract.getBuyerPayoutAddressString(), contract.getSellerPayoutAddressString(), - disputeResult.getArbitratorAddressAsString(), multiSigKeyPair, contract.getBuyerMultiSigPubKey(), contract.getSellerMultiSigPubKey(), @@ -727,7 +721,8 @@ public class DisputeManager { } private boolean isArbitrator(DisputeResult disputeResult) { - return disputeResult.getArbitratorAddressAsString().equals(walletService.getOrCreateAddressEntry(AddressEntry.Context.ARBITRATOR).getAddressString()); + return Arrays.equals(disputeResult.getArbitratorPubKey(), + walletService.getOrCreateAddressEntry(AddressEntry.Context.ARBITRATOR).getPubKey()); } public String getNrOfDisputes(boolean isBuyer, Contract contract) { diff --git a/core/src/main/java/io/bisq/btc/wallet/TradeWalletService.java b/core/src/main/java/io/bisq/btc/wallet/TradeWalletService.java index a073ef866b..c5ee3e2236 100644 --- a/core/src/main/java/io/bisq/btc/wallet/TradeWalletService.java +++ b/core/src/main/java/io/bisq/btc/wallet/TradeWalletService.java @@ -685,10 +685,8 @@ public class TradeWalletService { * @param depositTxSerialized Serialized deposit tx * @param buyerPayoutAmount The payout amount of the buyer. * @param sellerPayoutAmount The payout amount of the seller. - * @param arbitratorPayoutAmount The payout amount of the arbitrator. * @param buyerAddressString The address of the buyer. * @param sellerAddressString The address of the seller. - * @param arbitratorAddressString The address of the arbitrator. * @param arbitratorKeyPair The keypair of the arbitrator. * @param buyerPubKey The public key of the buyer. * @param sellerPubKey The public key of the seller. @@ -700,10 +698,8 @@ public class TradeWalletService { public byte[] arbitratorSignsDisputedPayoutTx(byte[] depositTxSerialized, Coin buyerPayoutAmount, Coin sellerPayoutAmount, - Coin arbitratorPayoutAmount, String buyerAddressString, String sellerAddressString, - String arbitratorAddressString, DeterministicKey arbitratorKeyPair, byte[] buyerPubKey, byte[] sellerPubKey, @@ -714,10 +710,8 @@ public class TradeWalletService { log.trace("depositTx " + depositTx.toString()); log.trace("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString()); log.trace("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString()); - log.trace("arbitratorPayoutAmount " + arbitratorPayoutAmount.toFriendlyString()); log.trace("buyerAddressString " + buyerAddressString); log.trace("sellerAddressString " + sellerAddressString); - log.trace("arbitratorAddressString " + arbitratorAddressString); log.trace("arbitratorKeyPair (not displayed for security reasons)"); log.info("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString()); log.info("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString()); @@ -731,8 +725,6 @@ public class TradeWalletService { preparedPayoutTx.addOutput(buyerPayoutAmount, new Address(params, buyerAddressString)); if (sellerPayoutAmount.isGreaterThan(Coin.ZERO)) preparedPayoutTx.addOutput(sellerPayoutAmount, new Address(params, sellerAddressString)); - if (arbitratorPayoutAmount.isGreaterThan(Coin.ZERO) && arbitratorAddressString != null) - preparedPayoutTx.addOutput(arbitratorPayoutAmount, new Address(params, arbitratorAddressString)); // take care of sorting! Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey); @@ -757,10 +749,8 @@ public class TradeWalletService { * @param arbitratorSignature DER encoded canonical signature of arbitrator * @param buyerPayoutAmount Payout amount of the buyer * @param sellerPayoutAmount Payout amount of the seller - * @param arbitratorPayoutAmount Payout amount for arbitrator * @param buyerAddressString The address of the buyer. * @param sellerAddressString The address of the seller. - * @param arbitratorAddressString The address of the arbitrator. * @param tradersMultiSigKeyPair The keypair for the MultiSig of the trader who calls that method * @param buyerPubKey The public key of the buyer. * @param sellerPubKey The public key of the seller. @@ -774,10 +764,8 @@ public class TradeWalletService { byte[] arbitratorSignature, Coin buyerPayoutAmount, Coin sellerPayoutAmount, - Coin arbitratorPayoutAmount, String buyerAddressString, String sellerAddressString, - String arbitratorAddressString, DeterministicKey tradersMultiSigKeyPair, byte[] buyerPubKey, byte[] sellerPubKey, @@ -791,10 +779,8 @@ public class TradeWalletService { log.trace("arbitratorSignature s " + ECKey.ECDSASignature.decodeFromDER(arbitratorSignature).s.toString()); log.trace("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString()); log.trace("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString()); - log.trace("arbitratorPayoutAmount " + arbitratorPayoutAmount.toFriendlyString()); log.trace("buyerAddressString " + buyerAddressString); log.trace("sellerAddressString " + sellerAddressString); - log.trace("arbitratorAddressString " + arbitratorAddressString); log.trace("tradersMultiSigKeyPair (not displayed for security reasons)"); log.info("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString()); log.info("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString()); @@ -808,8 +794,6 @@ public class TradeWalletService { payoutTx.addOutput(buyerPayoutAmount, new Address(params, buyerAddressString)); if (sellerPayoutAmount.isGreaterThan(Coin.ZERO)) payoutTx.addOutput(sellerPayoutAmount, new Address(params, sellerAddressString)); - if (arbitratorPayoutAmount.isGreaterThan(Coin.ZERO)) - payoutTx.addOutput(arbitratorPayoutAmount, new Address(params, arbitratorAddressString)); // take care of sorting! Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey); @@ -843,6 +827,7 @@ public class TradeWalletService { // Emergency payout tool. Used only in cased when the payput from the arbitrator does not work because some data // in the trade/dispute are messed up. + // We keep here arbitratorPayoutAmount just in case (requires cooperation from peer anyway) public Transaction emergencySignAndPublishPayoutTx(String depositTxHex, Coin buyerPayoutAmount, Coin sellerPayoutAmount, diff --git a/core/src/main/java/io/bisq/trade/protocol/trade/BuyerAsTakerProtocol.java b/core/src/main/java/io/bisq/trade/protocol/trade/BuyerAsTakerProtocol.java index f516dac44e..73ee78c2ff 100644 --- a/core/src/main/java/io/bisq/trade/protocol/trade/BuyerAsTakerProtocol.java +++ b/core/src/main/java/io/bisq/trade/protocol/trade/BuyerAsTakerProtocol.java @@ -121,7 +121,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol ProcessPublishDepositTxRequest.class, VerifyOffererAccount.class, VerifyAndSignContract.class, - TakerSignAndPublishDepositTxAsBuyer.class, + SignAndPublishDepositTxAsBuyer.class, SendDepositTxPublishedMessage.class, PublishTradeStatistics.class ); diff --git a/core/src/main/java/io/bisq/trade/protocol/trade/tasks/buyer/OffererCreatesAndSignsDepositTxAsBuyer.java b/core/src/main/java/io/bisq/trade/protocol/trade/tasks/buyer/OffererCreatesAndSignsDepositTxAsBuyer.java index ff13be8639..4089e3fee9 100644 --- a/core/src/main/java/io/bisq/trade/protocol/trade/tasks/buyer/OffererCreatesAndSignsDepositTxAsBuyer.java +++ b/core/src/main/java/io/bisq/trade/protocol/trade/tasks/buyer/OffererCreatesAndSignsDepositTxAsBuyer.java @@ -69,7 +69,7 @@ public class OffererCreatesAndSignsDepositTxAsBuyer extends TradeTask { Optional addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG); checkArgument(addressEntryOptional.isPresent(), "addressEntryOptional must be present"); AddressEntry buyerMultiSigAddressEntry = addressEntryOptional.get(); - buyerMultiSigAddressEntry.setCoinLockedInMultiSig(buyerInputAmount.subtract(trade.getTxFee())); + buyerMultiSigAddressEntry.setCoinLockedInMultiSig(buyerInputAmount); walletService.saveAddressEntryList(); Address offererAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE).getAddress(); Address offererChangeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress(); diff --git a/core/src/main/java/io/bisq/trade/protocol/trade/tasks/seller/OffererCreatesAndSignsDepositTxAsSeller.java b/core/src/main/java/io/bisq/trade/protocol/trade/tasks/seller/OffererCreatesAndSignsDepositTxAsSeller.java index 3224ddd4bf..841b99b3ee 100644 --- a/core/src/main/java/io/bisq/trade/protocol/trade/tasks/seller/OffererCreatesAndSignsDepositTxAsSeller.java +++ b/core/src/main/java/io/bisq/trade/protocol/trade/tasks/seller/OffererCreatesAndSignsDepositTxAsSeller.java @@ -68,7 +68,7 @@ public class OffererCreatesAndSignsDepositTxAsSeller extends TradeTask { Optional addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG); checkArgument(addressEntryOptional.isPresent(), "addressEntry must be set here."); AddressEntry sellerMultiSigAddressEntry = addressEntryOptional.get(); - sellerMultiSigAddressEntry.setCoinLockedInMultiSig(sellerInputAmount.subtract(trade.getTxFee())); + sellerMultiSigAddressEntry.setCoinLockedInMultiSig(sellerInputAmount); byte[] sellerMultiSigPubKey = processModel.getMyMultiSigPubKey(); checkArgument(Arrays.equals(sellerMultiSigPubKey, sellerMultiSigAddressEntry.getPubKey()), diff --git a/core/src/main/java/io/bisq/trade/protocol/trade/tasks/buyer/TakerSignAndPublishDepositTxAsBuyer.java b/core/src/main/java/io/bisq/trade/protocol/trade/tasks/taker/SignAndPublishDepositTxAsBuyer.java similarity index 92% rename from core/src/main/java/io/bisq/trade/protocol/trade/tasks/buyer/TakerSignAndPublishDepositTxAsBuyer.java rename to core/src/main/java/io/bisq/trade/protocol/trade/tasks/taker/SignAndPublishDepositTxAsBuyer.java index 279b4e8ed4..e1b6cbb01f 100644 --- a/core/src/main/java/io/bisq/trade/protocol/trade/tasks/buyer/TakerSignAndPublishDepositTxAsBuyer.java +++ b/core/src/main/java/io/bisq/trade/protocol/trade/tasks/taker/SignAndPublishDepositTxAsBuyer.java @@ -15,7 +15,7 @@ * along with bisq. If not, see . */ -package io.bisq.trade.protocol.trade.tasks.buyer; +package io.bisq.trade.protocol.trade.tasks.taker; import com.google.common.util.concurrent.FutureCallback; import io.bisq.btc.AddressEntry; @@ -38,11 +38,11 @@ import java.util.Optional; import static com.google.common.base.Preconditions.checkArgument; -public class TakerSignAndPublishDepositTxAsBuyer extends TradeTask { - private static final Logger log = LoggerFactory.getLogger(TakerSignAndPublishDepositTxAsBuyer.class); +public class SignAndPublishDepositTxAsBuyer extends TradeTask { + private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTxAsBuyer.class); @SuppressWarnings({"WeakerAccess", "unused"}) - public TakerSignAndPublishDepositTxAsBuyer(TaskRunner taskHandler, Trade trade) { + public SignAndPublishDepositTxAsBuyer(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } @@ -67,7 +67,7 @@ public class TakerSignAndPublishDepositTxAsBuyer extends TradeTask { checkArgument(addressEntryOptional.isPresent(), "addressEntryOptional must be present"); AddressEntry buyerMultiSigAddressEntry = addressEntryOptional.get(); Coin buyerInput = Coin.valueOf(buyerInputs.stream().mapToLong(input -> input.value).sum()); - buyerMultiSigAddressEntry.setCoinLockedInMultiSig(buyerInput.subtract(trade.getTxFee())); + buyerMultiSigAddressEntry.setCoinLockedInMultiSig(buyerInput.subtract(trade.getTxFee().multiply(2))); TradingPeer tradingPeer = processModel.tradingPeer; byte[] buyerMultiSigPubKey = processModel.getMyMultiSigPubKey(); checkArgument(Arrays.equals(buyerMultiSigPubKey, buyerMultiSigAddressEntry.getPubKey()), diff --git a/core/src/main/java/io/bisq/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java b/core/src/main/java/io/bisq/trade/protocol/trade/tasks/taker/SignAndPublishDepositTxAsSeller.java similarity index 97% rename from core/src/main/java/io/bisq/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java rename to core/src/main/java/io/bisq/trade/protocol/trade/tasks/taker/SignAndPublishDepositTxAsSeller.java index c1f46cbbf5..969e91cd02 100644 --- a/core/src/main/java/io/bisq/trade/protocol/trade/tasks/seller/SignAndPublishDepositTxAsSeller.java +++ b/core/src/main/java/io/bisq/trade/protocol/trade/tasks/taker/SignAndPublishDepositTxAsSeller.java @@ -15,7 +15,7 @@ * along with bisq. If not, see . */ -package io.bisq.trade.protocol.trade.tasks.seller; +package io.bisq.trade.protocol.trade.tasks.taker; import com.google.common.util.concurrent.FutureCallback; import io.bisq.btc.AddressEntry; @@ -71,7 +71,7 @@ public class SignAndPublishDepositTxAsSeller extends TradeTask { "sellerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id); Coin sellerInput = Coin.valueOf(sellerInputs.stream().mapToLong(input -> input.value).sum()); - sellerMultiSigAddressEntry.setCoinLockedInMultiSig(sellerInput.subtract(trade.getTxFee())); + sellerMultiSigAddressEntry.setCoinLockedInMultiSig(sellerInput.subtract(trade.getTxFee().multiply(2))); TradingPeer tradingPeer = processModel.tradingPeer; Transaction depositTx = processModel.getTradeWalletService().takerSignsAndPublishesDepositTx( true, diff --git a/gui/src/main/java/io/bisq/gui/main/overlays/windows/DisputeSummaryWindow.java b/gui/src/main/java/io/bisq/gui/main/overlays/windows/DisputeSummaryWindow.java index e9ad75ae3e..502b0bcc8f 100644 --- a/gui/src/main/java/io/bisq/gui/main/overlays/windows/DisputeSummaryWindow.java +++ b/gui/src/main/java/io/bisq/gui/main/overlays/windows/DisputeSummaryWindow.java @@ -36,7 +36,6 @@ import io.bisq.messages.arbitration.DisputeResult; import io.bisq.messages.trade.offer.payload.Offer; import io.bisq.messages.trade.payload.Contract; import javafx.beans.binding.Bindings; -import javafx.beans.binding.ObjectBinding; import javafx.beans.value.ChangeListener; import javafx.geometry.Insets; import javafx.geometry.VPos; @@ -69,25 +68,23 @@ public class DisputeSummaryWindow extends Overlay { private final TradeWalletService tradeWalletService; private Dispute dispute; private Optional finalizeDisputeHandlerOptional = Optional.empty(); - private ToggleGroup tradeAmountToggleGroup; + private ToggleGroup tradeAmountToggleGroup, reasonToggleGroup; private DisputeResult disputeResult; - private RadioButton buyerIsWinnerRadioButton, sellerIsWinnerRadioButton, shareRadioButton, customRadioButton, loserPaysFeeRadioButton, splitFeeRadioButton, - waiveFeeRadioButton, reasonWasBugRadioButton, reasonWasUsabilityIssueRadioButton, reasonProtocolViolationRadioButton, reasonNoReplyRadioButton, reasonWasScamRadioButton, reasonWasOtherRadioButton; + private RadioButton buyerGetsTradeAmountRadioButton, sellerGetsTradeAmountRadioButton, + buyerGetsAllRadioButton, sellerGetsAllRadioButton, customRadioButton; + private RadioButton reasonWasBugRadioButton, reasonWasUsabilityIssueRadioButton, + reasonProtocolViolationRadioButton, reasonNoReplyRadioButton, reasonWasScamRadioButton, + reasonWasOtherRadioButton, reasonWasBankRadioButton; private Optional peersDisputeOptional; - private Coin arbitratorPayoutAmount, winnerPayoutAmount, loserPayoutAmount, stalematePayoutAmount; - private ToggleGroup feeToggleGroup, reasonToggleGroup; private String role; private TextArea summaryNotesTextArea; - // keep a reference to not get GCed - private ObjectBinding> feePaymentPolicyChanged; - - private ChangeListener> feePaymentPolicyListener; - private ChangeListener shareRadioButtonSelectedListener, customRadioButtonSelectedListener; - private ChangeListener feeToggleSelectionListener, reasonToggleSelectionListener; - private InputTextField buyerPayoutAmountInputTextField, sellerPayoutAmountInputTextField, arbitratorPayoutAmountInputTextField; - private ChangeListener buyerPayoutAmountListener, sellerPayoutAmountListener, arbitratorPayoutAmountListener; + private ChangeListener customRadioButtonSelectedListener; + private ChangeListener reasonToggleSelectionListener; + private InputTextField buyerPayoutAmountInputTextField, sellerPayoutAmountInputTextField; + private ChangeListener buyerPayoutAmountListener, sellerPayoutAmountListener; private CheckBox isLoserPublisherCheckBox; + private ChangeListener tradeAmountToggleGroupListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -108,7 +105,7 @@ public class DisputeSummaryWindow extends Overlay { this.dispute = dispute; rowIndex = -1; - width = 850; + width = 1050; createGridPane(); addContent(); display(); @@ -126,21 +123,15 @@ public class DisputeSummaryWindow extends Overlay { @Override protected void cleanup() { - if (feePaymentPolicyChanged != null) - feePaymentPolicyChanged.removeListener(feePaymentPolicyListener); - - if (shareRadioButton != null) - shareRadioButton.selectedProperty().removeListener(shareRadioButtonSelectedListener); - - if (feeToggleGroup != null) - feeToggleGroup.selectedToggleProperty().removeListener(feeToggleSelectionListener); - if (reasonToggleGroup != null) reasonToggleGroup.selectedToggleProperty().removeListener(reasonToggleSelectionListener); if (customRadioButton != null) customRadioButton.selectedProperty().removeListener(customRadioButtonSelectedListener); + if (tradeAmountToggleGroup != null) + tradeAmountToggleGroup.selectedToggleProperty().removeListener(tradeAmountToggleGroupListener); + removePayoutAmountListeners(); } @@ -183,7 +174,6 @@ public class DisputeSummaryWindow extends Overlay { addCheckboxes(); addTradeAmountPayoutControls(); - addFeeControls(); addPayoutAmountTextFields(); addReasonControls(); @@ -193,8 +183,6 @@ public class DisputeSummaryWindow extends Overlay { DisputeResult peersDisputeResult = peersDisputeOptional.get().disputeResultProperty().get(); disputeResult.setBuyerPayoutAmount(peersDisputeResult.getBuyerPayoutAmount()); disputeResult.setSellerPayoutAmount(peersDisputeResult.getSellerPayoutAmount()); - disputeResult.setArbitratorPayoutAmount(peersDisputeResult.getArbitratorPayoutAmount()); - disputeResult.setDisputeFeePolicy(peersDisputeResult.getDisputeFeePolicy()); disputeResult.setWinner(peersDisputeResult.getWinner()); disputeResult.setLoserIsPublisher(peersDisputeResult.isLoserPublisher()); disputeResult.setReason(peersDisputeResult.getReason()); @@ -203,23 +191,18 @@ public class DisputeSummaryWindow extends Overlay { if (disputeResult.getBuyerPayoutAmount() != null) { log.debug("buyerPayoutAmount " + disputeResult.getBuyerPayoutAmount().toFriendlyString()); log.debug("sellerPayoutAmount " + disputeResult.getSellerPayoutAmount().toFriendlyString()); - log.debug("arbitratorPayoutAmount " + disputeResult.getArbitratorPayoutAmount().toFriendlyString()); } - buyerIsWinnerRadioButton.setDisable(true); - sellerIsWinnerRadioButton.setDisable(true); - shareRadioButton.setDisable(true); + buyerGetsTradeAmountRadioButton.setDisable(true); + buyerGetsAllRadioButton.setDisable(true); + sellerGetsTradeAmountRadioButton.setDisable(true); + sellerGetsAllRadioButton.setDisable(true); customRadioButton.setDisable(true); - loserPaysFeeRadioButton.setDisable(true); - splitFeeRadioButton.setDisable(true); - waiveFeeRadioButton.setDisable(true); buyerPayoutAmountInputTextField.setDisable(true); sellerPayoutAmountInputTextField.setDisable(true); - arbitratorPayoutAmountInputTextField.setDisable(true); buyerPayoutAmountInputTextField.setEditable(false); sellerPayoutAmountInputTextField.setEditable(false); - arbitratorPayoutAmountInputTextField.setEditable(false); reasonWasBugRadioButton.setDisable(true); reasonWasUsabilityIssueRadioButton.setDisable(true); @@ -227,25 +210,17 @@ public class DisputeSummaryWindow extends Overlay { reasonNoReplyRadioButton.setDisable(true); reasonWasScamRadioButton.setDisable(true); reasonWasOtherRadioButton.setDisable(true); + reasonWasBankRadioButton.setDisable(true); isLoserPublisherCheckBox.setDisable(true); isLoserPublisherCheckBox.setSelected(peersDisputeResult.isLoserPublisher()); - calculatePayoutAmounts(disputeResult.getDisputeFeePolicy()); + applyPayoutAmounts(tradeAmountToggleGroup.selectedToggleProperty().get()); applyTradeAmountRadioButtonStates(); } else { - applyPayoutAmounts(disputeResult.disputeFeePolicyProperty().get(), tradeAmountToggleGroup.selectedToggleProperty().get()); - feePaymentPolicyChanged = Bindings.createObjectBinding( - () -> new Tuple2<>(disputeResult.disputeFeePolicyProperty().get(), tradeAmountToggleGroup.selectedToggleProperty().get()), - disputeResult.disputeFeePolicyProperty(), - tradeAmountToggleGroup.selectedToggleProperty()); - feePaymentPolicyListener = (observable, oldValue, newValue) -> applyPayoutAmounts(newValue.first, newValue.second); - feePaymentPolicyChanged.addListener(feePaymentPolicyListener); - isLoserPublisherCheckBox.setSelected(false); } - setFeeRadioButtonState(); setReasonRadioButtonState(); addSummaryNotes(); @@ -299,55 +274,46 @@ public class DisputeSummaryWindow extends Overlay { Label distributionLabel = addLabel(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.payout"), 10); GridPane.setValignment(distributionLabel, VPos.TOP); - buyerIsWinnerRadioButton = new RadioButton(Res.get("disputeSummaryWindow.payout.buyerWinner")); - sellerIsWinnerRadioButton = new RadioButton(Res.get("disputeSummaryWindow.payout.sellerWinner")); - shareRadioButton = new RadioButton(Res.get("disputeSummaryWindow.payout.both")); + buyerGetsTradeAmountRadioButton = new RadioButton(Res.get("disputeSummaryWindow.payout.getsTradeAmount", + Res.get("shared.buyer"))); + buyerGetsAllRadioButton = new RadioButton(Res.get("disputeSummaryWindow.payout.getsAll", + Res.get("shared.buyer"))); + sellerGetsTradeAmountRadioButton = new RadioButton(Res.get("disputeSummaryWindow.payout.getsTradeAmount", + Res.get("shared.seller"))); + sellerGetsAllRadioButton = new RadioButton(Res.get("disputeSummaryWindow.payout.getsAll", + Res.get("shared.seller"))); + customRadioButton = new RadioButton(Res.get("disputeSummaryWindow.payout.custom")); VBox radioButtonPane = new VBox(); radioButtonPane.setSpacing(10); - radioButtonPane.getChildren().addAll(buyerIsWinnerRadioButton, sellerIsWinnerRadioButton, shareRadioButton, customRadioButton); + radioButtonPane.getChildren().addAll(buyerGetsTradeAmountRadioButton, buyerGetsAllRadioButton, + sellerGetsTradeAmountRadioButton, sellerGetsAllRadioButton, + customRadioButton); GridPane.setRowIndex(radioButtonPane, rowIndex); GridPane.setColumnIndex(radioButtonPane, 1); GridPane.setMargin(radioButtonPane, new Insets(10, 0, 0, 0)); gridPane.getChildren().add(radioButtonPane); tradeAmountToggleGroup = new ToggleGroup(); - buyerIsWinnerRadioButton.setToggleGroup(tradeAmountToggleGroup); - sellerIsWinnerRadioButton.setToggleGroup(tradeAmountToggleGroup); - shareRadioButton.setToggleGroup(tradeAmountToggleGroup); + buyerGetsTradeAmountRadioButton.setToggleGroup(tradeAmountToggleGroup); + buyerGetsAllRadioButton.setToggleGroup(tradeAmountToggleGroup); + sellerGetsTradeAmountRadioButton.setToggleGroup(tradeAmountToggleGroup); + sellerGetsAllRadioButton.setToggleGroup(tradeAmountToggleGroup); customRadioButton.setToggleGroup(tradeAmountToggleGroup); - shareRadioButtonSelectedListener = (observable, oldValue, newValue) -> { - if (newValue) { - loserPaysFeeRadioButton.setSelected(false); - if (splitFeeRadioButton != null && !dispute.isSupportTicket()) - splitFeeRadioButton.setSelected(true); - - if (waiveFeeRadioButton != null && dispute.isSupportTicket()) - waiveFeeRadioButton.setSelected(true); - } - - loserPaysFeeRadioButton.setDisable(newValue); - }; - shareRadioButton.selectedProperty().addListener(shareRadioButtonSelectedListener); + tradeAmountToggleGroupListener = (observable, oldValue, newValue) -> applyPayoutAmounts(newValue); + tradeAmountToggleGroup.selectedToggleProperty().addListener(tradeAmountToggleGroupListener); buyerPayoutAmountListener = (observable1, oldValue1, newValue1) -> applyCustomAmounts(buyerPayoutAmountInputTextField); sellerPayoutAmountListener = (observable1, oldValue1, newValue1) -> applyCustomAmounts(sellerPayoutAmountInputTextField); - arbitratorPayoutAmountListener = (observable1, oldValue1, newValue1) -> applyCustomAmounts(arbitratorPayoutAmountInputTextField); customRadioButtonSelectedListener = (observable, oldValue, newValue) -> { buyerPayoutAmountInputTextField.setEditable(newValue); sellerPayoutAmountInputTextField.setEditable(newValue); - arbitratorPayoutAmountInputTextField.setEditable(newValue); - - loserPaysFeeRadioButton.setDisable(newValue); - splitFeeRadioButton.setDisable(newValue); - waiveFeeRadioButton.setDisable(newValue); if (newValue) { buyerPayoutAmountInputTextField.textProperty().addListener(buyerPayoutAmountListener); sellerPayoutAmountInputTextField.textProperty().addListener(sellerPayoutAmountListener); - arbitratorPayoutAmountInputTextField.textProperty().addListener(arbitratorPayoutAmountListener); } else { removePayoutAmountListeners(); } @@ -362,21 +328,18 @@ public class DisputeSummaryWindow extends Overlay { if (sellerPayoutAmountInputTextField != null && sellerPayoutAmountListener != null) sellerPayoutAmountInputTextField.textProperty().removeListener(sellerPayoutAmountListener); - if (arbitratorPayoutAmountInputTextField != null && arbitratorPayoutAmountListener != null) - arbitratorPayoutAmountInputTextField.textProperty().removeListener(arbitratorPayoutAmountListener); } private boolean isPayoutAmountValid() { Coin buyerAmount = formatter.parseToCoin(buyerPayoutAmountInputTextField.getText()); Coin sellerAmount = formatter.parseToCoin(sellerPayoutAmountInputTextField.getText()); - Coin arbitratorAmount = formatter.parseToCoin(arbitratorPayoutAmountInputTextField.getText()); Contract contract = dispute.getContract(); Coin tradeAmount = contract.getTradeAmount(); Offer offer = contract.offer; Coin available = tradeAmount .add(offer.getBuyerSecurityDeposit()) .add(offer.getSellerSecurityDeposit()); - Coin totalAmount = buyerAmount.add(sellerAmount).add(arbitratorAmount); + Coin totalAmount = buyerAmount.add(sellerAmount); return (totalAmount.compareTo(available) == 0); } @@ -384,75 +347,34 @@ public class DisputeSummaryWindow extends Overlay { Contract contract = dispute.getContract(); Coin buyerAmount = formatter.parseToCoin(buyerPayoutAmountInputTextField.getText()); Coin sellerAmount = formatter.parseToCoin(sellerPayoutAmountInputTextField.getText()); - Coin arbitratorAmount = formatter.parseToCoin(arbitratorPayoutAmountInputTextField.getText()); Offer offer = contract.offer; Coin available = contract.getTradeAmount(). add(offer.getBuyerSecurityDeposit()) .add(offer.getSellerSecurityDeposit()); - Coin totalAmount = buyerAmount.add(sellerAmount).add(arbitratorAmount); + Coin totalAmount = buyerAmount.add(sellerAmount); if (totalAmount.compareTo(available) > 0) { new Popup<>().warning(Res.get("disputeSummaryWindow.payout.adjustAmount", available.toFriendlyString())) .show(); if (inputTextField == buyerPayoutAmountInputTextField) { - buyerAmount = available.subtract(sellerAmount).subtract(arbitratorAmount); + buyerAmount = available.subtract(sellerAmount); inputTextField.setText(formatter.formatCoin(buyerAmount)); } else if (inputTextField == sellerPayoutAmountInputTextField) { - sellerAmount = available.subtract(buyerAmount).subtract(arbitratorAmount); + sellerAmount = available.subtract(buyerAmount); inputTextField.setText(formatter.formatCoin(sellerAmount)); - } else if (inputTextField == arbitratorPayoutAmountInputTextField) { - arbitratorAmount = available.subtract(sellerAmount).subtract(buyerAmount); - inputTextField.setText(formatter.formatCoin(arbitratorAmount)); } } disputeResult.setBuyerPayoutAmount(buyerAmount); disputeResult.setSellerPayoutAmount(sellerAmount); - disputeResult.setArbitratorPayoutAmount(arbitratorAmount); - if (buyerAmount.compareTo(sellerAmount) == 0) - disputeResult.setWinner(DisputeResult.Winner.STALE_MATE); - else if (buyerAmount.compareTo(sellerAmount) > 0) + if (buyerAmount.compareTo(sellerAmount) > 0) disputeResult.setWinner(DisputeResult.Winner.BUYER); else disputeResult.setWinner(DisputeResult.Winner.SELLER); } - private void addFeeControls() { - Label splitFeeLabel = addLabel(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.arbitrationFee"), 10); - GridPane.setValignment(splitFeeLabel, VPos.TOP); - - loserPaysFeeRadioButton = new RadioButton(Res.get("disputeSummaryWindow.arbitrationFee.looserPay")); - splitFeeRadioButton = new RadioButton(Res.get("disputeSummaryWindow.split")); - waiveFeeRadioButton = new RadioButton(Res.get("disputeSummaryWindow.arbitrationFee.waive")); - HBox feeRadioButtonPane = new HBox(); - feeRadioButtonPane.setSpacing(20); - feeRadioButtonPane.getChildren().addAll(loserPaysFeeRadioButton, splitFeeRadioButton, waiveFeeRadioButton); - GridPane.setRowIndex(feeRadioButtonPane, rowIndex); - GridPane.setColumnIndex(feeRadioButtonPane, 1); - GridPane.setMargin(feeRadioButtonPane, new Insets(10, 0, 10, 0)); - gridPane.getChildren().add(feeRadioButtonPane); - - feeToggleGroup = new ToggleGroup(); - loserPaysFeeRadioButton.setToggleGroup(feeToggleGroup); - splitFeeRadioButton.setToggleGroup(feeToggleGroup); - waiveFeeRadioButton.setToggleGroup(feeToggleGroup); - - feeToggleSelectionListener = (observable, oldValue, newValue) -> { - if (newValue == loserPaysFeeRadioButton) - disputeResult.setDisputeFeePolicy(DisputeResult.DisputeFeePolicy.LOSER); - else if (newValue == splitFeeRadioButton) - disputeResult.setDisputeFeePolicy(DisputeResult.DisputeFeePolicy.SPLIT); - else if (newValue == waiveFeeRadioButton) - disputeResult.setDisputeFeePolicy(DisputeResult.DisputeFeePolicy.WAIVE); - }; - feeToggleGroup.selectedToggleProperty().addListener(feeToggleSelectionListener); - - if (dispute.isSupportTicket()) - feeToggleGroup.selectToggle(waiveFeeRadioButton); - } - private void addPayoutAmountTextFields() { buyerPayoutAmountInputTextField = addLabelInputTextField(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.payoutAmount.buyer")).second; @@ -462,28 +384,10 @@ public class DisputeSummaryWindow extends Overlay { Res.get("disputeSummaryWindow.payoutAmount.seller")).second; sellerPayoutAmountInputTextField.setEditable(false); - arbitratorPayoutAmountInputTextField = addLabelInputTextField(gridPane, ++rowIndex, - Res.get("disputeSummaryWindow.payoutAmount.arbitrator")).second; - arbitratorPayoutAmountInputTextField.setEditable(false); - isLoserPublisherCheckBox = addLabelCheckBox(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.payoutAmount.invert")).second; } - private void setFeeRadioButtonState() { - switch (disputeResult.getDisputeFeePolicy()) { - case LOSER: - feeToggleGroup.selectToggle(loserPaysFeeRadioButton); - break; - case SPLIT: - feeToggleGroup.selectToggle(splitFeeRadioButton); - break; - case WAIVE: - feeToggleGroup.selectToggle(waiveFeeRadioButton); - break; - } - } - private void addReasonControls() { Label label = addLabel(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.reason"), 10); GridPane.setValignment(label, VPos.TOP); @@ -492,6 +396,7 @@ public class DisputeSummaryWindow extends Overlay { reasonProtocolViolationRadioButton = new RadioButton(Res.get("disputeSummaryWindow.reason.protocolViolation")); reasonNoReplyRadioButton = new RadioButton(Res.get("disputeSummaryWindow.reason.noReply")); reasonWasScamRadioButton = new RadioButton(Res.get("disputeSummaryWindow.reason.scam")); + reasonWasBankRadioButton = new RadioButton(Res.get("disputeSummaryWindow.reason.bank")); reasonWasOtherRadioButton = new RadioButton(Res.get("disputeSummaryWindow.reason.other")); //TODO add banks as reason @@ -499,7 +404,7 @@ public class DisputeSummaryWindow extends Overlay { feeRadioButtonPane.setSpacing(20); feeRadioButtonPane.getChildren().addAll(reasonWasBugRadioButton, reasonWasUsabilityIssueRadioButton, reasonProtocolViolationRadioButton, reasonNoReplyRadioButton, - reasonWasScamRadioButton, reasonWasOtherRadioButton); + reasonWasBankRadioButton, reasonWasScamRadioButton, reasonWasOtherRadioButton); GridPane.setRowIndex(feeRadioButtonPane, rowIndex); GridPane.setColumnIndex(feeRadioButtonPane, 1); GridPane.setMargin(feeRadioButtonPane, new Insets(10, 0, 10, 0)); @@ -512,6 +417,7 @@ public class DisputeSummaryWindow extends Overlay { reasonNoReplyRadioButton.setToggleGroup(reasonToggleGroup); reasonWasScamRadioButton.setToggleGroup(reasonToggleGroup); reasonWasOtherRadioButton.setToggleGroup(reasonToggleGroup); + reasonWasBankRadioButton.setToggleGroup(reasonToggleGroup); reasonToggleSelectionListener = (observable, oldValue, newValue) -> { if (newValue == reasonWasBugRadioButton) @@ -524,6 +430,8 @@ public class DisputeSummaryWindow extends Overlay { disputeResult.setReason(DisputeResult.Reason.NO_REPLY); else if (newValue == reasonWasScamRadioButton) disputeResult.setReason(DisputeResult.Reason.SCAM); + else if (newValue == reasonWasBankRadioButton) + disputeResult.setReason(DisputeResult.Reason.BANK_PROBLEMS); else if (newValue == reasonWasOtherRadioButton) disputeResult.setReason(DisputeResult.Reason.OTHER); }; @@ -548,6 +456,9 @@ public class DisputeSummaryWindow extends Overlay { case SCAM: reasonToggleGroup.selectToggle(reasonWasScamRadioButton); break; + case BANK_PROBLEMS: + reasonToggleGroup.selectToggle(reasonWasBankRadioButton); + break; case OTHER: reasonToggleGroup.selectToggle(reasonWasOtherRadioButton); break; @@ -582,8 +493,7 @@ public class DisputeSummaryWindow extends Overlay { tradeAmountToggleGroup.selectedToggleProperty(), summaryNotesTextArea.textProperty(), buyerPayoutAmountInputTextField.textProperty(), - sellerPayoutAmountInputTextField.textProperty(), - arbitratorPayoutAmountInputTextField.textProperty())); + sellerPayoutAmountInputTextField.textProperty())); Button cancelButton = tuple.second; @@ -592,8 +502,7 @@ public class DisputeSummaryWindow extends Overlay { if (dispute.getDepositTxSerialized() != null) { try { AddressEntry arbitratorAddressEntry = walletService.getOrCreateAddressEntry(AddressEntry.Context.ARBITRATOR); - disputeResult.setArbitratorAddressAsString(arbitratorAddressEntry.getAddressString()); - disputeResult.setArbitratorPubKey(arbitratorAddressEntry.getPubKey()); + disputeResult.setArbitratorPubKey(walletService.getOrCreateAddressEntry(AddressEntry.Context.ARBITRATOR).getPubKey()); /* byte[] depositTxSerialized, Coin buyerPayoutAmount, @@ -610,10 +519,8 @@ public class DisputeSummaryWindow extends Overlay { dispute.getDepositTxSerialized(), disputeResult.getBuyerPayoutAmount(), disputeResult.getSellerPayoutAmount(), - disputeResult.getArbitratorPayoutAmount(), contract.getBuyerPayoutAddressString(), contract.getSellerPayoutAddressString(), - arbitratorAddressEntry.getAddressString(), arbitratorAddressEntry.getKeyPair(), contract.getBuyerMultiSigPubKey(), contract.getSellerMultiSigPubKey(), @@ -636,7 +543,6 @@ public class DisputeSummaryWindow extends Overlay { formatter.booleanToYesNo(disputeResult.screenCastProperty().get()), formatter.formatCoinWithCode(disputeResult.getBuyerPayoutAmount()), formatter.formatCoinWithCode(disputeResult.getSellerPayoutAmount()), - formatter.formatCoinWithCode(disputeResult.getArbitratorPayoutAmount()), disputeResult.summaryNotesProperty().get()); dispute.setIsClosed(true); @@ -669,88 +575,68 @@ public class DisputeSummaryWindow extends Overlay { // Controller /////////////////////////////////////////////////////////////////////////////////////////// - private void applyPayoutAmounts(DisputeResult.DisputeFeePolicy feePayment, Toggle selectedTradeAmountToggle) { - if (selectedTradeAmountToggle != customRadioButton) { - calculatePayoutAmounts(feePayment); - if (selectedTradeAmountToggle != null) { - applyPayoutAmountsToDisputeResult(selectedTradeAmountToggle); - applyTradeAmountRadioButtonStates(); - } + private void applyPayoutAmounts(Toggle selectedTradeAmountToggle) { + if (selectedTradeAmountToggle != customRadioButton && selectedTradeAmountToggle != null) { + applyPayoutAmountsToDisputeResult(selectedTradeAmountToggle); + applyTradeAmountRadioButtonStates(); } } - //TODO - private void calculatePayoutAmounts(DisputeResult.DisputeFeePolicy feePayment) { - Contract contract = dispute.getContract(); - Coin buyerSecurityDeposit = contract.offer.getBuyerSecurityDeposit(); - Coin sellerSecurityDeposit = contract.offer.getSellerSecurityDeposit(); - Coin winnerRefund; - Coin loserRefund; - switch (feePayment) { - case SPLIT: - winnerRefund = buyerSecurityDeposit.divide(2L); - loserRefund = winnerRefund; - arbitratorPayoutAmount = buyerSecurityDeposit; - break; - case WAIVE: - winnerRefund = buyerSecurityDeposit; - loserRefund = buyerSecurityDeposit; - arbitratorPayoutAmount = Coin.ZERO; - break; - case LOSER: - default: - winnerRefund = buyerSecurityDeposit; - loserRefund = Coin.ZERO; - arbitratorPayoutAmount = buyerSecurityDeposit; - break; - } - - winnerPayoutAmount = contract.getTradeAmount().add(winnerRefund); - loserPayoutAmount = loserRefund; - stalematePayoutAmount = contract.getTradeAmount().divide(2L).add(winnerRefund); - } - private void applyPayoutAmountsToDisputeResult(Toggle selectedTradeAmountToggle) { - if (selectedTradeAmountToggle == buyerIsWinnerRadioButton) { - disputeResult.setBuyerPayoutAmount(winnerPayoutAmount); - disputeResult.setSellerPayoutAmount(loserPayoutAmount); + Contract contract = dispute.getContract(); + Coin buyerSecurityDeposit = contract.offer.getBuyerSecurityDeposit(); + Coin sellerSecurityDeposit = contract.offer.getSellerSecurityDeposit(); + Coin tradeAmount = contract.getTradeAmount(); + if (selectedTradeAmountToggle == buyerGetsTradeAmountRadioButton) { + disputeResult.setBuyerPayoutAmount(tradeAmount.add(buyerSecurityDeposit)); + disputeResult.setSellerPayoutAmount(sellerSecurityDeposit); disputeResult.setWinner(DisputeResult.Winner.BUYER); - - buyerPayoutAmountInputTextField.setText(formatter.formatCoin(winnerPayoutAmount)); - sellerPayoutAmountInputTextField.setText(formatter.formatCoin(loserPayoutAmount)); - } else if (selectedTradeAmountToggle == sellerIsWinnerRadioButton) { - disputeResult.setBuyerPayoutAmount(loserPayoutAmount); - disputeResult.setSellerPayoutAmount(winnerPayoutAmount); + } else if (selectedTradeAmountToggle == buyerGetsAllRadioButton) { + disputeResult.setBuyerPayoutAmount(tradeAmount + .add(buyerSecurityDeposit) + .add(sellerSecurityDeposit)); + disputeResult.setSellerPayoutAmount(Coin.ZERO); + disputeResult.setWinner(DisputeResult.Winner.BUYER); + } else if (selectedTradeAmountToggle == sellerGetsTradeAmountRadioButton) { + disputeResult.setBuyerPayoutAmount(buyerSecurityDeposit); + disputeResult.setSellerPayoutAmount(tradeAmount.add(sellerSecurityDeposit)); + disputeResult.setWinner(DisputeResult.Winner.SELLER); + } else if (selectedTradeAmountToggle == sellerGetsAllRadioButton) { + disputeResult.setBuyerPayoutAmount(Coin.ZERO); + disputeResult.setSellerPayoutAmount(tradeAmount + .add(sellerSecurityDeposit) + .add(buyerSecurityDeposit)); disputeResult.setWinner(DisputeResult.Winner.SELLER); - - buyerPayoutAmountInputTextField.setText(formatter.formatCoin(loserPayoutAmount)); - sellerPayoutAmountInputTextField.setText(formatter.formatCoin(winnerPayoutAmount)); - } else if (selectedTradeAmountToggle == shareRadioButton) { - disputeResult.setBuyerPayoutAmount(stalematePayoutAmount); - disputeResult.setSellerPayoutAmount(stalematePayoutAmount); - disputeResult.setWinner(DisputeResult.Winner.STALE_MATE); - - buyerPayoutAmountInputTextField.setText(formatter.formatCoin(stalematePayoutAmount)); - sellerPayoutAmountInputTextField.setText(formatter.formatCoin(stalematePayoutAmount)); } - disputeResult.setArbitratorPayoutAmount(arbitratorPayoutAmount); - arbitratorPayoutAmountInputTextField.setText(formatter.formatCoin(arbitratorPayoutAmount)); + + buyerPayoutAmountInputTextField.setText(formatter.formatCoin(disputeResult.getBuyerPayoutAmount())); + sellerPayoutAmountInputTextField.setText(formatter.formatCoin(disputeResult.getSellerPayoutAmount())); } private void applyTradeAmountRadioButtonStates() { + Contract contract = dispute.getContract(); + Coin buyerSecurityDeposit = contract.offer.getBuyerSecurityDeposit(); + Coin sellerSecurityDeposit = contract.offer.getSellerSecurityDeposit(); + Coin tradeAmount = contract.getTradeAmount(); + Coin buyerPayoutAmount = disputeResult.getBuyerPayoutAmount(); Coin sellerPayoutAmount = disputeResult.getSellerPayoutAmount(); buyerPayoutAmountInputTextField.setText(formatter.formatCoin(buyerPayoutAmount)); sellerPayoutAmountInputTextField.setText(formatter.formatCoin(sellerPayoutAmount)); - arbitratorPayoutAmountInputTextField.setText(formatter.formatCoin(disputeResult.getArbitratorPayoutAmount())); - if (buyerPayoutAmount.equals(winnerPayoutAmount) && sellerPayoutAmount.equals(loserPayoutAmount)) { - buyerIsWinnerRadioButton.setSelected(true); - } else if (sellerPayoutAmount.equals(winnerPayoutAmount) && buyerPayoutAmount.equals(loserPayoutAmount)) { - sellerIsWinnerRadioButton.setSelected(true); - } else if (sellerPayoutAmount.equals(buyerPayoutAmount)) { - shareRadioButton.setSelected(true); + if (buyerPayoutAmount.equals(tradeAmount.add(buyerSecurityDeposit)) && + sellerPayoutAmount.equals(sellerSecurityDeposit)) { + buyerGetsTradeAmountRadioButton.setSelected(true); + } else if (buyerPayoutAmount.equals(tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit)) && + sellerPayoutAmount.equals(Coin.ZERO)) { + buyerGetsAllRadioButton.setSelected(true); + } else if (sellerPayoutAmount.equals(tradeAmount.add(sellerSecurityDeposit)) + && buyerPayoutAmount.equals(buyerSecurityDeposit)) { + sellerGetsTradeAmountRadioButton.setSelected(true); + } else if (sellerPayoutAmount.equals(tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit)) + && buyerPayoutAmount.equals(Coin.ZERO)) { + sellerGetsAllRadioButton.setSelected(true); } else { customRadioButton.setSelected(true); } diff --git a/network/src/main/java/io/bisq/messages/arbitration/DisputeResult.java b/network/src/main/java/io/bisq/messages/arbitration/DisputeResult.java index 041ba79010..ea4abdae27 100644 --- a/network/src/main/java/io/bisq/messages/arbitration/DisputeResult.java +++ b/network/src/main/java/io/bisq/messages/arbitration/DisputeResult.java @@ -21,7 +21,10 @@ import com.google.protobuf.ByteString; import io.bisq.app.Version; import io.bisq.common.wire.Payload; import io.bisq.common.wire.proto.Messages; -import javafx.beans.property.*; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; import lombok.EqualsAndHashCode; import org.bitcoinj.core.Coin; import org.slf4j.Logger; @@ -37,31 +40,25 @@ public final class DisputeResult implements Payload { private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; private static final Logger log = LoggerFactory.getLogger(DisputeResult.class); - public enum DisputeFeePolicy { - LOSER, - SPLIT, - WAIVE - } - public enum Winner { BUYER, - SELLER, - STALE_MATE + SELLER } // only append new values as we use the ordinal value + // bank problems, no reply, buyer not sent public enum Reason { OTHER, BUG, USABILITY, SCAM, PROTOCOL_VIOLATION, - NO_REPLY + NO_REPLY, + BANK_PROBLEMS } public final String tradeId; public final int traderId; - private DisputeFeePolicy disputeFeePolicy; private Winner winner; private int reasonOrdinal = Reason.OTHER.ordinal(); @@ -74,8 +71,6 @@ public final class DisputeResult implements Payload { private byte[] arbitratorSignature; private long buyerPayoutAmount; private long sellerPayoutAmount; - private long arbitratorPayoutAmount; - private String arbitratorAddressAsString; private byte[] arbitratorPubKey; private long closeDate; private boolean isLoserPublisher; @@ -83,25 +78,22 @@ public final class DisputeResult implements Payload { transient private BooleanProperty tamperProofEvidenceProperty = new SimpleBooleanProperty(); transient private BooleanProperty idVerificationProperty = new SimpleBooleanProperty(); transient private BooleanProperty screenCastProperty = new SimpleBooleanProperty(); - transient private ObjectProperty feePaymentPolicyProperty = new SimpleObjectProperty<>(); transient private StringProperty summaryNotesProperty = new SimpleStringProperty(); public DisputeResult(String tradeId, int traderId) { this.tradeId = tradeId; this.traderId = traderId; - this.disputeFeePolicy = DisputeFeePolicy.LOSER; init(); } - public DisputeResult(String tradeId, int traderId, DisputeFeePolicy disputeFeePolicy, Winner winner, + public DisputeResult(String tradeId, int traderId, Winner winner, int reasonOrdinal, boolean tamperProofEvidence, boolean idVerification, boolean screenCast, String summaryNotes, DisputeCommunicationMessage disputeCommunicationMessage, byte[] arbitratorSignature, long buyerPayoutAmount, long sellerPayoutAmount, - long arbitratorPayoutAmount, String arbitratorAddressAsString, byte[] arbitratorPubKey, + byte[] arbitratorPubKey, long closeDate, boolean isLoserPublisher) { this.tradeId = tradeId; this.traderId = traderId; - this.disputeFeePolicy = disputeFeePolicy; this.winner = winner; this.reasonOrdinal = reasonOrdinal; this.tamperProofEvidence = tamperProofEvidence; @@ -112,8 +104,6 @@ public final class DisputeResult implements Payload { this.arbitratorSignature = arbitratorSignature; this.buyerPayoutAmount = buyerPayoutAmount; this.sellerPayoutAmount = sellerPayoutAmount; - this.arbitratorPayoutAmount = arbitratorPayoutAmount; - this.arbitratorAddressAsString = arbitratorAddressAsString; this.arbitratorPubKey = arbitratorPubKey; this.closeDate = closeDate; this.isLoserPublisher = isLoserPublisher; @@ -133,7 +123,6 @@ public final class DisputeResult implements Payload { tamperProofEvidenceProperty = new SimpleBooleanProperty(tamperProofEvidence); idVerificationProperty = new SimpleBooleanProperty(idVerification); screenCastProperty = new SimpleBooleanProperty(screenCast); - feePaymentPolicyProperty = new SimpleObjectProperty<>(disputeFeePolicy); summaryNotesProperty = new SimpleStringProperty(summaryNotes); tamperProofEvidenceProperty.addListener((observable, oldValue, newValue) -> { @@ -145,9 +134,6 @@ public final class DisputeResult implements Payload { screenCastProperty.addListener((observable, oldValue, newValue) -> { screenCast = newValue; }); - feePaymentPolicyProperty.addListener((observable, oldValue, newValue) -> { - disputeFeePolicy = newValue; - }); summaryNotesProperty.addListener((observable, oldValue, newValue) -> { summaryNotes = newValue; }); @@ -165,19 +151,6 @@ public final class DisputeResult implements Payload { return screenCastProperty; } - public void setDisputeFeePolicy(DisputeFeePolicy disputeFeePolicy) { - this.disputeFeePolicy = disputeFeePolicy; - feePaymentPolicyProperty.set(disputeFeePolicy); - } - - public ReadOnlyObjectProperty disputeFeePolicyProperty() { - return feePaymentPolicyProperty; - } - - public DisputeFeePolicy getDisputeFeePolicy() { - return disputeFeePolicy; - } - public void setReason(Reason reason) { this.reasonOrdinal = reason.ordinal(); } @@ -229,22 +202,6 @@ public final class DisputeResult implements Payload { return Coin.valueOf(sellerPayoutAmount); } - public void setArbitratorPayoutAmount(Coin arbitratorPayoutAmount) { - this.arbitratorPayoutAmount = arbitratorPayoutAmount.value; - } - - public Coin getArbitratorPayoutAmount() { - return Coin.valueOf(arbitratorPayoutAmount); - } - - public void setArbitratorAddressAsString(String arbitratorAddressAsString) { - this.arbitratorAddressAsString = arbitratorAddressAsString; - } - - public String getArbitratorAddressAsString() { - return arbitratorAddressAsString; - } - public void setArbitratorPubKey(byte[] arbitratorPubKey) { this.arbitratorPubKey = arbitratorPubKey; } @@ -282,7 +239,6 @@ public final class DisputeResult implements Payload { return Messages.DisputeResult.newBuilder() .setTradeId(tradeId) .setTraderId(traderId) - .setDisputeFeePolicy(Messages.DisputeResult.DisputeFeePolicy.forNumber(disputeFeePolicy.ordinal())) .setWinner(Messages.DisputeResult.Winner.forNumber(winner.ordinal())) .setReasonOrdinal(reasonOrdinal) .setTamperProofEvidence(tamperProofEvidence) @@ -293,8 +249,6 @@ public final class DisputeResult implements Payload { .setArbitratorSignature(ByteString.copyFrom(arbitratorSignature)) .setBuyerPayoutAmount(buyerPayoutAmount) .setSellerPayoutAmount(sellerPayoutAmount) - .setArbitratorPayoutAmount(arbitratorPayoutAmount) - .setArbitratorAddressAsString(arbitratorAddressAsString) .setArbitratorPubKey(ByteString.copyFrom(arbitratorPubKey)) .setCloseDate(closeDate) .setIsLoserPublisher(isLoserPublisher).build(); diff --git a/network/src/main/java/io/bisq/messages/trade/offer/payload/Offer.java b/network/src/main/java/io/bisq/messages/trade/offer/payload/Offer.java index 20d305a7b2..9d7b27e389 100644 --- a/network/src/main/java/io/bisq/messages/trade/offer/payload/Offer.java +++ b/network/src/main/java/io/bisq/messages/trade/offer/payload/Offer.java @@ -387,7 +387,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload checkArgument(getDate().getTime() > 0, "Date must not be 0. date=" + getDate().toString()); - + checkNotNull(getArbitratorNodeAddresses(), "Arbitrator is null"); checkNotNull(getCurrencyCode(), "Currency is null"); checkNotNull(getDirection(), "Direction is null"); @@ -395,7 +395,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload checkNotNull(getPubKeyRing(), "pubKeyRing is null"); checkNotNull(getVersionNr(), "VersionNr is null"); checkArgument(getMaxTradePeriod() > 0, "maxTradePeriod must be positive. maxTradePeriod=" + getMaxTradePeriod()); - + // TODO check upper and lower bounds for fiat // TODO check rest of new parameters } diff --git a/network/src/main/java/io/bisq/p2p/network/ProtoBufferUtilities.java b/network/src/main/java/io/bisq/p2p/network/ProtoBufferUtilities.java index bde41a9214..68b561cdf9 100644 --- a/network/src/main/java/io/bisq/p2p/network/ProtoBufferUtilities.java +++ b/network/src/main/java/io/bisq/p2p/network/ProtoBufferUtilities.java @@ -250,17 +250,15 @@ public class ProtoBufferUtilities { Messages.DisputeResult disputeResultproto = disputeResultMessage.getDisputeResult(); DisputeResult disputeResult = new DisputeResult(disputeResultproto.getTradeId(), - disputeResultproto.getTraderId(), DisputeResult.DisputeFeePolicy.valueOf(disputeResultproto.getDisputeFeePolicy().name()), + disputeResultproto.getTraderId(), DisputeResult.Winner.valueOf(disputeResultproto.getWinner().name()), disputeResultproto.getReasonOrdinal(), disputeResultproto.getTamperProofEvidence(), disputeResultproto.getIdVerification(), disputeResultproto.getScreenCast(), disputeResultproto.getSummaryNotes(), (DisputeCommunicationMessage) getDisputeCommunicationMessage(disputeResultproto.getDisputeCommunicationMessage()), disputeResultproto.getArbitratorSignature().toByteArray(), disputeResultproto.getBuyerPayoutAmount(), - disputeResultproto.getSellerPayoutAmount(), disputeResultproto.getArbitratorPayoutAmount(), - disputeResultproto.getArbitratorAddressAsString(), + disputeResultproto.getSellerPayoutAmount(), disputeResultproto.getArbitratorPubKey().toByteArray(), disputeResultproto.getCloseDate(), disputeResultproto.getIsLoserPublisher()); - disputeResult.setArbitratorAddressAsString(disputeResultproto.getArbitratorAddressAsString()); return new DisputeResultMessage(disputeResult, getNodeAddress(disputeResultMessage.getMyNodeAddress())); }