forked from bisq-network/bisq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FinalizeMediatedPayoutTx.java
121 lines (95 loc) · 5.42 KB
/
FinalizeMediatedPayoutTx.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.bisq_v1.tasks.mediation;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.offer.Offer;
import bisq.core.trade.model.bisq_v1.Contract;
import bisq.core.trade.model.bisq_v1.Trade;
import bisq.core.trade.protocol.bisq_v1.model.TradingPeer;
import bisq.core.trade.protocol.bisq_v1.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.crypto.DeterministicKey;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class FinalizeMediatedPayoutTx extends TradeTask {
public FinalizeMediatedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
Transaction depositTx = checkNotNull(trade.getDepositTx());
String tradeId = trade.getId();
TradingPeer tradingPeer = processModel.getTradePeer();
BtcWalletService walletService = processModel.getBtcWalletService();
Offer offer = checkNotNull(trade.getOffer(), "offer must not be null");
Coin tradeAmount = checkNotNull(trade.getTradeAmount(), "tradeAmount must not be null");
Contract contract = checkNotNull(trade.getContract(), "contract must not be null");
checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null");
byte[] mySignature = checkNotNull(processModel.getMediatedPayoutTxSignature(),
"processModel.getTxSignatureFromMediation must not be null");
byte[] peersSignature = checkNotNull(tradingPeer.getMediatedPayoutTxSignature(),
"tradingPeer.getTxSignatureFromMediation must not be null");
boolean isMyRoleBuyer = contract.isMyRoleBuyer(processModel.getPubKeyRing());
byte[] buyerSignature = isMyRoleBuyer ? mySignature : peersSignature;
byte[] sellerSignature = isMyRoleBuyer ? peersSignature : mySignature;
Coin totalPayoutAmount = offer.getBuyerSecurityDeposit().add(tradeAmount).add(offer.getSellerSecurityDeposit());
Coin buyerPayoutAmount = Coin.valueOf(processModel.getBuyerPayoutAmountFromMediation());
Coin sellerPayoutAmount = Coin.valueOf(processModel.getSellerPayoutAmountFromMediation());
checkArgument(totalPayoutAmount.equals(buyerPayoutAmount.add(sellerPayoutAmount)),
"Payout amount does not match buyerPayoutAmount=" + buyerPayoutAmount.toFriendlyString() +
"; sellerPayoutAmount=" + sellerPayoutAmount);
String myPayoutAddressString = walletService.getOrCreateAddressEntry(tradeId, AddressEntry.Context.TRADE_PAYOUT).getAddressString();
String peersPayoutAddressString = tradingPeer.getPayoutAddressString();
String buyerPayoutAddressString = isMyRoleBuyer ? myPayoutAddressString : peersPayoutAddressString;
String sellerPayoutAddressString = isMyRoleBuyer ? peersPayoutAddressString : myPayoutAddressString;
byte[] myMultiSigPubKey = processModel.getMyMultiSigPubKey();
byte[] peersMultiSigPubKey = tradingPeer.getMultiSigPubKey();
byte[] buyerMultiSigPubKey = isMyRoleBuyer ? myMultiSigPubKey : peersMultiSigPubKey;
byte[] sellerMultiSigPubKey = isMyRoleBuyer ? peersMultiSigPubKey : myMultiSigPubKey;
DeterministicKey multiSigKeyPair = walletService.getMultiSigKeyPair(tradeId, myMultiSigPubKey);
checkArgument(Arrays.equals(myMultiSigPubKey,
walletService.getOrCreateAddressEntry(tradeId, AddressEntry.Context.MULTI_SIG).getPubKey()),
"myMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + tradeId);
Transaction transaction = processModel.getTradeWalletService().finalizeMediatedPayoutTx(
depositTx,
buyerSignature,
sellerSignature,
buyerPayoutAmount,
sellerPayoutAmount,
buyerPayoutAddressString,
sellerPayoutAddressString,
multiSigKeyPair,
buyerMultiSigPubKey,
sellerMultiSigPubKey
);
trade.setPayoutTx(transaction);
processModel.getTradeManager().requestPersistence();
walletService.resetCoinLockedInMultiSigAddressEntry(tradeId);
complete();
} catch (Throwable t) {
failed(t);
}
}
}