cleanup trade states, consolidate protocol tasks, remove old tasks

This commit is contained in:
woodser 2022-07-31 10:38:52 -04:00
parent 3d43ae1f20
commit 333b7421f5
76 changed files with 114 additions and 3807 deletions

View File

@ -18,7 +18,7 @@ import static bisq.core.trade.Trade.Phase.DEPOSIT_UNLOCKED;
import static bisq.core.trade.Trade.Phase.PAYMENT_SENT;
import static bisq.core.trade.Trade.Phase.PAYOUT_PUBLISHED;
import static bisq.core.trade.Trade.State.BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG;
import static bisq.core.trade.Trade.State.DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN;
import static bisq.core.trade.Trade.State.DEPOSIT_TXS_UNLOCKED_IN_BLOCKCHAIN;
import static bisq.core.trade.Trade.State.SELLER_RECEIVED_PAYMENT_SENT_MSG;
import static java.lang.String.format;
import static java.lang.System.out;
@ -79,7 +79,7 @@ public class AbstractTradeTest extends AbstractOfferTest {
GrpcClient grpcClient,
String tradeId) {
Predicate<TradeInfo> isTradeInDepositUnlockedStateAndPhase = (t) ->
t.getState().equals(DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN.name())
t.getState().equals(DEPOSIT_TXS_UNLOCKED_IN_BLOCKCHAIN.name())
&& t.getPhase().equals(DEPOSIT_UNLOCKED.name());
String userName = toUserName.apply(grpcClient);
@ -94,7 +94,7 @@ public class AbstractTradeTest extends AbstractOfferTest {
i);
genBtcBlocksThenWait(1, 4_000);
} else {
EXPECTED_PROTOCOL_STATUS.setState(DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN)
EXPECTED_PROTOCOL_STATUS.setState(DEPOSIT_TXS_UNLOCKED_IN_BLOCKCHAIN)
.setPhase(DEPOSIT_UNLOCKED)
.setDepositPublished(true)
.setDepositConfirmed(true);

View File

@ -40,21 +40,14 @@ import bisq.core.support.dispute.refund.refundagent.RefundAgent;
import bisq.core.support.messages.ChatMessage;
import bisq.core.trade.messages.PaymentSentMessage;
import bisq.core.trade.messages.PayoutTxPublishedMessage;
import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest;
import bisq.core.trade.messages.DelayedPayoutTxSignatureResponse;
import bisq.core.trade.messages.DepositRequest;
import bisq.core.trade.messages.DepositResponse;
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
import bisq.core.trade.messages.DepositTxMessage;
import bisq.core.trade.messages.InitMultisigRequest;
import bisq.core.trade.messages.InitTradeRequest;
import bisq.core.trade.messages.InputsForDepositTxRequest;
import bisq.core.trade.messages.InputsForDepositTxResponse;
import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage;
import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage;
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
import bisq.core.trade.messages.PaymentReceivedMessage;
import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage;
import bisq.core.trade.messages.RefreshTradeStateRequest;
import bisq.core.trade.messages.SignContractRequest;
import bisq.core.trade.messages.SignContractResponse;
@ -170,18 +163,6 @@ public class CoreNetworkProtoResolver extends CoreProtoResolver implements Netwo
return UpdateMultisigRequest.fromProto(proto.getUpdateMultisigRequest(), this, messageVersion);
case UPDATE_MULTISIG_RESPONSE:
return UpdateMultisigResponse.fromProto(proto.getUpdateMultisigResponse(), this, messageVersion);
case INPUTS_FOR_DEPOSIT_TX_REQUEST:
return InputsForDepositTxRequest.fromProto(proto.getInputsForDepositTxRequest(), this, messageVersion);
case INPUTS_FOR_DEPOSIT_TX_RESPONSE:
return InputsForDepositTxResponse.fromProto(proto.getInputsForDepositTxResponse(), this, messageVersion);
case DEPOSIT_TX_MESSAGE:
return DepositTxMessage.fromProto(proto.getDepositTxMessage(), messageVersion);
case DELAYED_PAYOUT_TX_SIGNATURE_REQUEST:
return DelayedPayoutTxSignatureRequest.fromProto(proto.getDelayedPayoutTxSignatureRequest(), messageVersion);
case DELAYED_PAYOUT_TX_SIGNATURE_RESPONSE:
return DelayedPayoutTxSignatureResponse.fromProto(proto.getDelayedPayoutTxSignatureResponse(), messageVersion);
case DEPOSIT_TX_AND_DELAYED_PAYOUT_TX_MESSAGE:
return DepositTxAndDelayedPayoutTxMessage.fromProto(proto.getDepositTxAndDelayedPayoutTxMessage(), messageVersion);
case PAYMENT_SENT_MESSAGE:
return PaymentSentMessage.fromProto(proto.getPaymentSentMessage(), messageVersion);
@ -190,8 +171,6 @@ public class CoreNetworkProtoResolver extends CoreProtoResolver implements Netwo
case PAYOUT_TX_PUBLISHED_MESSAGE:
return PayoutTxPublishedMessage.fromProto(proto.getPayoutTxPublishedMessage(), messageVersion);
case PEER_PUBLISHED_DELAYED_PAYOUT_TX_MESSAGE:
return PeerPublishedDelayedPayoutTxMessage.fromProto(proto.getPeerPublishedDelayedPayoutTxMessage(), messageVersion);
case TRADER_SIGNED_WITNESS_MESSAGE:
return TraderSignedWitnessMessage.fromProto(proto.getTraderSignedWitnessMessage(), messageVersion);

View File

@ -104,8 +104,8 @@ public abstract class Trade implements Tradable, Model {
///////////////////////////////////////////////////////////////////////////////////////////
public enum State {
// #################### Phase INIT
// When trade protocol starts no funds are on stake
// trade initialization
PREPARATION(Phase.INIT),
MULTISIG_PREPARED(Phase.INIT),
MULTISIG_MADE(Phase.INIT),
@ -113,79 +113,47 @@ public abstract class Trade implements Tradable, Model {
CONTRACT_SIGNATURE_REQUESTED(Phase.INIT),
CONTRACT_SIGNED(Phase.INIT),
// At first part maker/taker have different roles
// taker perspective
// #################### Phase TAKER_FEE_PUBLISHED
TAKER_PUBLISHED_TAKER_FEE_TX(Phase.TAKER_FEE_PUBLISHED),
// deposit requested
SENT_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED),
SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED),
STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), //not a mailbox msg, not used...
SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED),
// PUBLISH_DEPOSIT_TX_REQUEST
// maker perspective
MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED),
MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED),
MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), //not a mailbox msg, not used...
MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED),
// deposit published
SAW_DEPOSIT_TXS_IN_NETWORK(Phase.DEPOSIT_PUBLISHED), // TODO: seeing in network usually happens after arbitrator publishes
ARBITRATOR_PUBLISHED_DEPOSIT_TXS(Phase.DEPOSIT_PUBLISHED),
// taker perspective
TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), // Not used anymore
// deposit confirmed (TODO)
// Alternatively the taker could have seen the deposit tx earlier before he received the DEPOSIT_TX_PUBLISHED_MSG
TAKER_SAW_DEPOSIT_TX_IN_NETWORK(Phase.DEPOSIT_PUBLISHED),
// deposit unlocked
DEPOSIT_TXS_UNLOCKED_IN_BLOCKCHAIN(Phase.DEPOSIT_UNLOCKED),
// #################### Phase DEPOSIT_PUBLISHED
// We changes order in trade protocol of publishing deposit tx and sending it to the peer.
// Now we send it first to the peer and only if that succeeds we publish it to avoid likelihood of
// failed trades. We do not want to change the order of the enum though so we keep it here as it was originally.
ARBITRATOR_PUBLISHED_DEPOSIT_TX(Phase.DEPOSIT_PUBLISHED),
// DEPOSIT_TX_PUBLISHED_MSG
// taker perspective
TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG(Phase.DEPOSIT_PUBLISHED),
TAKER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG(Phase.DEPOSIT_PUBLISHED),
TAKER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG(Phase.DEPOSIT_PUBLISHED),
TAKER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG(Phase.DEPOSIT_PUBLISHED),
// maker perspective
MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG(Phase.DEPOSIT_PUBLISHED),
// Alternatively the maker could have seen the deposit tx earlier before he received the DEPOSIT_TX_PUBLISHED_MSG
MAKER_SAW_DEPOSIT_TX_IN_NETWORK(Phase.DEPOSIT_PUBLISHED),
// #################### Phase DEPOSIT_CONFIRMED
DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN(Phase.DEPOSIT_UNLOCKED),
// #################### Phase PAYMENT_SENT
// payment sent
BUYER_CONFIRMED_IN_UI_PAYMENT_SENT(Phase.PAYMENT_SENT),
BUYER_SENT_PAYMENT_SENT_MSG(Phase.PAYMENT_SENT),
BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG(Phase.PAYMENT_SENT),
BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG(Phase.PAYMENT_SENT),
BUYER_SEND_FAILED_PAYMENT_SENT_MSG(Phase.PAYMENT_SENT),
SELLER_RECEIVED_PAYMENT_SENT_MSG(Phase.PAYMENT_SENT),
// #################### Phase PAYMENT_RECEIVED
// note that this state can also be triggered by auto confirmation feature
// payment received
SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT(Phase.PAYMENT_RECEIVED),
SELLER_SENT_PAYMENT_RECEIVED_MSG(Phase.PAYMENT_RECEIVED),
SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG(Phase.PAYMENT_RECEIVED),
SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG(Phase.PAYMENT_RECEIVED),
SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG(Phase.PAYMENT_RECEIVED),
// #################### Phase PAYOUT_PUBLISHED
// payout published
SELLER_PUBLISHED_PAYOUT_TX(Phase.PAYOUT_PUBLISHED), // TODO (woodser): this enum is over used, like during arbitration
SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG(Phase.PAYOUT_PUBLISHED),
SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG(Phase.PAYOUT_PUBLISHED),
SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG(Phase.PAYOUT_PUBLISHED),
SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG(Phase.PAYOUT_PUBLISHED),
BUYER_RECEIVED_PAYOUT_TX_PUBLISHED_MSG(Phase.PAYOUT_PUBLISHED),
// Alternatively the maker could have seen the payout tx earlier before he received the PAYOUT_TX_PUBLISHED_MSG
BUYER_SAW_PAYOUT_TX_IN_NETWORK(Phase.PAYOUT_PUBLISHED),
BUYER_PUBLISHED_PAYOUT_TX(Phase.PAYOUT_PUBLISHED),
// #################### Phase WITHDRAWN
// trade completed
WITHDRAW_COMPLETED(Phase.WITHDRAWN);
@NotNull
@ -891,7 +859,7 @@ public abstract class Trade implements Tradable, Model {
return;
}
} else {
setStateIfValidTransitionTo(this instanceof MakerTrade ? Trade.State.MAKER_SAW_DEPOSIT_TX_IN_NETWORK : Trade.State.TAKER_SAW_DEPOSIT_TX_IN_NETWORK);
setStateIfValidTransitionTo(Trade.State.SAW_DEPOSIT_TXS_IN_NETWORK);
}
}
@ -934,7 +902,7 @@ public abstract class Trade implements Tradable, Model {
xmrWalletService.removeWalletListener(depositTxListener); // remove listener when notified
depositTxListener = null; // prevent re-applying trade state in subsequent requests
} else if (txs.size() == 2) {
setStateIfValidTransitionTo(this instanceof MakerTrade ? Trade.State.MAKER_SAW_DEPOSIT_TX_IN_NETWORK : Trade.State.TAKER_SAW_DEPOSIT_TX_IN_NETWORK);
setStateIfValidTransitionTo(Trade.State.SAW_DEPOSIT_TXS_IN_NETWORK);
}
}
};
@ -1488,7 +1456,7 @@ public abstract class Trade implements Tradable, Model {
// As setState is called here from the trade itself we cannot trigger a requestPersistence call.
// But as we get setupConfidenceListener called at startup anyway there is no issue if it would not be
// persisted in case the shutdown routine did not persist the trade.
setStateIfValidTransitionTo(State.DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN); // TODO (woodser): for xmr this means deposit txs have unlocked after 10 confirmations
setStateIfValidTransitionTo(State.DEPOSIT_TXS_UNLOCKED_IN_BLOCKCHAIN); // TODO (woodser): for xmr this means deposit txs have unlocked after 10 confirmations
}
}

View File

@ -41,7 +41,6 @@ import bisq.core.trade.messages.DepositRequest;
import bisq.core.trade.messages.DepositResponse;
import bisq.core.trade.messages.InitMultisigRequest;
import bisq.core.trade.messages.InitTradeRequest;
import bisq.core.trade.messages.InputsForDepositTxRequest;
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
import bisq.core.trade.messages.SignContractRequest;
import bisq.core.trade.messages.SignContractResponse;
@ -242,9 +241,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
@Override
public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer) {
NetworkEnvelope networkEnvelope = message.getNetworkEnvelope();
if (networkEnvelope instanceof InputsForDepositTxRequest) {
//handleTakeOfferRequest(peer, (InputsForDepositTxRequest) networkEnvelope); // ignore bisq requests
} else if (networkEnvelope instanceof InitTradeRequest) {
if (networkEnvelope instanceof InitTradeRequest) {
handleInitTradeRequest((InitTradeRequest) networkEnvelope, peer);
} else if (networkEnvelope instanceof InitMultisigRequest) {
handleInitMultisigRequest((InitMultisigRequest) networkEnvelope, peer);

View File

@ -1,98 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.messages;
import bisq.network.p2p.DirectMessage;
import bisq.network.p2p.NodeAddress;
import bisq.common.app.Version;
import bisq.common.util.Utilities;
import com.google.protobuf.ByteString;
import lombok.EqualsAndHashCode;
import lombok.Value;
@EqualsAndHashCode(callSuper = true)
@Value
public final class DelayedPayoutTxSignatureRequest extends TradeMessage implements DirectMessage {
private final NodeAddress senderNodeAddress;
private final byte[] delayedPayoutTx;
private final byte[] delayedPayoutTxSellerSignature;
public DelayedPayoutTxSignatureRequest(String uid,
String tradeId,
NodeAddress senderNodeAddress,
byte[] delayedPayoutTx,
byte[] delayedPayoutTxSellerSignature) {
this(Version.getP2PMessageVersion(),
uid,
tradeId,
senderNodeAddress,
delayedPayoutTx,
delayedPayoutTxSellerSignature);
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
private DelayedPayoutTxSignatureRequest(String messageVersion,
String uid,
String tradeId,
NodeAddress senderNodeAddress,
byte[] delayedPayoutTx,
byte[] delayedPayoutTxSellerSignature) {
super(messageVersion, tradeId, uid);
this.senderNodeAddress = senderNodeAddress;
this.delayedPayoutTx = delayedPayoutTx;
this.delayedPayoutTxSellerSignature = delayedPayoutTxSellerSignature;
}
@Override
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
.setDelayedPayoutTxSignatureRequest(protobuf.DelayedPayoutTxSignatureRequest.newBuilder()
.setUid(uid)
.setTradeId(tradeId)
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
.setDelayedPayoutTx(ByteString.copyFrom(delayedPayoutTx))
.setDelayedPayoutTxSellerSignature(ByteString.copyFrom(delayedPayoutTxSellerSignature)))
.build();
}
public static DelayedPayoutTxSignatureRequest fromProto(protobuf.DelayedPayoutTxSignatureRequest proto,
String messageVersion) {
return new DelayedPayoutTxSignatureRequest(messageVersion,
proto.getUid(),
proto.getTradeId(),
NodeAddress.fromProto(proto.getSenderNodeAddress()),
proto.getDelayedPayoutTx().toByteArray(),
proto.getDelayedPayoutTxSellerSignature().toByteArray());
}
@Override
public String toString() {
return "DelayedPayoutTxSignatureRequest{" +
"\n senderNodeAddress=" + senderNodeAddress +
",\n delayedPayoutTx=" + Utilities.bytesAsHexString(delayedPayoutTx) +
",\n delayedPayoutTxSellerSignature=" + Utilities.bytesAsHexString(delayedPayoutTxSellerSignature) +
"\n} " + super.toString();
}
}

View File

@ -1,99 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.messages;
import bisq.network.p2p.DirectMessage;
import bisq.network.p2p.NodeAddress;
import bisq.common.app.Version;
import bisq.common.util.Utilities;
import com.google.protobuf.ByteString;
import lombok.EqualsAndHashCode;
import lombok.Value;
@EqualsAndHashCode(callSuper = true)
@Value
public final class DelayedPayoutTxSignatureResponse extends TradeMessage implements DirectMessage {
private final NodeAddress senderNodeAddress;
private final byte[] delayedPayoutTxBuyerSignature;
private final byte[] depositTx;
public DelayedPayoutTxSignatureResponse(String uid,
String tradeId,
NodeAddress senderNodeAddress,
byte[] delayedPayoutTxBuyerSignature,
byte[] depositTx) {
this(Version.getP2PMessageVersion(),
uid,
tradeId,
senderNodeAddress,
delayedPayoutTxBuyerSignature,
depositTx);
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
private DelayedPayoutTxSignatureResponse(String messageVersion,
String uid,
String tradeId,
NodeAddress senderNodeAddress,
byte[] delayedPayoutTxBuyerSignature,
byte[] depositTx) {
super(messageVersion, tradeId, uid);
this.senderNodeAddress = senderNodeAddress;
this.delayedPayoutTxBuyerSignature = delayedPayoutTxBuyerSignature;
this.depositTx = depositTx;
}
@Override
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
.setDelayedPayoutTxSignatureResponse(protobuf.DelayedPayoutTxSignatureResponse.newBuilder()
.setUid(uid)
.setTradeId(tradeId)
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
.setDelayedPayoutTxBuyerSignature(ByteString.copyFrom(delayedPayoutTxBuyerSignature))
.setDepositTx(ByteString.copyFrom(depositTx))
)
.build();
}
public static DelayedPayoutTxSignatureResponse fromProto(protobuf.DelayedPayoutTxSignatureResponse proto,
String messageVersion) {
return new DelayedPayoutTxSignatureResponse(messageVersion,
proto.getUid(),
proto.getTradeId(),
NodeAddress.fromProto(proto.getSenderNodeAddress()),
proto.getDelayedPayoutTxBuyerSignature().toByteArray(),
proto.getDepositTx().toByteArray());
}
@Override
public String toString() {
return "DelayedPayoutTxSignatureResponse{" +
"\n senderNodeAddress=" + senderNodeAddress +
",\n delayedPayoutTxBuyerSignature=" + Utilities.bytesAsHexString(delayedPayoutTxBuyerSignature) +
",\n depositTx=" + Utilities.bytesAsHexString(depositTx) +
"\n} " + super.toString();
}
}

View File

@ -1,98 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.messages;
import bisq.network.p2p.NodeAddress;
import bisq.common.app.Version;
import bisq.common.util.Utilities;
import com.google.protobuf.ByteString;
import lombok.EqualsAndHashCode;
import lombok.Value;
// It is the last message in the take offer phase. We use MailboxMessage instead of DirectMessage to add more tolerance
// in case of network issues and as the message does not trigger further protocol execution.
@EqualsAndHashCode(callSuper = true)
@Value
public final class DepositTxAndDelayedPayoutTxMessage extends TradeMailboxMessage {
private final NodeAddress senderNodeAddress;
private final byte[] depositTx;
private final byte[] delayedPayoutTx;
public DepositTxAndDelayedPayoutTxMessage(String uid,
String tradeId,
NodeAddress senderNodeAddress,
byte[] depositTx,
byte[] delayedPayoutTx) {
this(Version.getP2PMessageVersion(),
uid,
tradeId,
senderNodeAddress,
depositTx,
delayedPayoutTx);
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
private DepositTxAndDelayedPayoutTxMessage(String messageVersion,
String uid,
String tradeId,
NodeAddress senderNodeAddress,
byte[] depositTx,
byte[] delayedPayoutTx) {
super(messageVersion, tradeId, uid);
this.senderNodeAddress = senderNodeAddress;
this.depositTx = depositTx;
this.delayedPayoutTx = delayedPayoutTx;
}
@Override
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
.setDepositTxAndDelayedPayoutTxMessage(protobuf.DepositTxAndDelayedPayoutTxMessage.newBuilder()
.setUid(uid)
.setTradeId(tradeId)
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
.setDepositTx(ByteString.copyFrom(depositTx))
.setDelayedPayoutTx(ByteString.copyFrom(delayedPayoutTx)))
.build();
}
public static DepositTxAndDelayedPayoutTxMessage fromProto(protobuf.DepositTxAndDelayedPayoutTxMessage proto,
String messageVersion) {
return new DepositTxAndDelayedPayoutTxMessage(messageVersion,
proto.getUid(),
proto.getTradeId(),
NodeAddress.fromProto(proto.getSenderNodeAddress()),
proto.getDepositTx().toByteArray(),
proto.getDelayedPayoutTx().toByteArray());
}
@Override
public String toString() {
return "DepositTxAndDelayedPayoutTxMessage{" +
"\n senderNodeAddress=" + senderNodeAddress +
",\n depositTx=" + Utilities.bytesAsHexString(depositTx) +
",\n delayedPayoutTx=" + Utilities.bytesAsHexString(delayedPayoutTx) +
"\n} " + super.toString();
}
}

View File

@ -1,86 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.messages;
import bisq.network.p2p.DirectMessage;
import bisq.network.p2p.NodeAddress;
import bisq.common.app.Version;
import bisq.common.proto.ProtoUtil;
import java.util.Optional;
import lombok.EqualsAndHashCode;
import lombok.Value;
import javax.annotation.Nullable;
// It is the last message in the take offer phase. We use MailboxMessage instead of DirectMessage to add more tolerance
// in case of network issues and as the message does not trigger further protocol execution.
@EqualsAndHashCode(callSuper = true)
@Value
public final class DepositTxMessage extends TradeMessage implements DirectMessage {
private final NodeAddress senderNodeAddress;
@Nullable
private final String tradeFeeTxId;
@Nullable
private final String depositTxId;
public DepositTxMessage(String uid,
String tradeId,
NodeAddress senderNodeAddress,
String tradeFeeTxId,
String depositTxId) {
super(Version.getP2PMessageVersion(), tradeId, uid);
this.senderNodeAddress = senderNodeAddress;
this.tradeFeeTxId = tradeFeeTxId;
this.depositTxId = depositTxId;
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
protobuf.DepositTxMessage.Builder builder = protobuf.DepositTxMessage.newBuilder()
.setTradeId(tradeId)
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
.setUid(uid);
Optional.ofNullable(tradeFeeTxId).ifPresent(e -> builder.setTradeFeeTxId(tradeFeeTxId));
Optional.ofNullable(depositTxId).ifPresent(e -> builder.setDepositTxId(depositTxId));
return getNetworkEnvelopeBuilder().setDepositTxMessage(builder).build();
}
public static DepositTxMessage fromProto(protobuf.DepositTxMessage proto, String messageVersion) {
return new DepositTxMessage(proto.getUid(),
proto.getTradeId(),
NodeAddress.fromProto(proto.getSenderNodeAddress()),
ProtoUtil.stringOrNullFromProto(proto.getTradeFeeTxId()),
ProtoUtil.stringOrNullFromProto(proto.getDepositTxId()));
}
@Override
public String toString() {
return "DepositTxMessage{" +
"\n senderNodeAddress=" + senderNodeAddress +
",\n tradeFeeTxId=" + tradeFeeTxId +
",\n depositTxId=" + depositTxId +
"\n} " + super.toString();
}
}

View File

@ -1,229 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.messages;
import bisq.core.btc.model.RawTransactionInput;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.proto.CoreProtoResolver;
import bisq.network.p2p.DirectMessage;
import bisq.network.p2p.NodeAddress;
import bisq.common.crypto.PubKeyRing;
import bisq.common.proto.ProtoUtil;
import bisq.common.util.Utilities;
import com.google.protobuf.ByteString;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
import lombok.Value;
import javax.annotation.Nullable;
@EqualsAndHashCode(callSuper = true)
@Value
public final class InputsForDepositTxRequest extends TradeMessage implements DirectMessage {
private final NodeAddress senderNodeAddress;
private final long tradeAmount;
private final long tradePrice;
private final long txFee;
private final long takerFee;
private final List<RawTransactionInput> rawTransactionInputs;
private final long changeOutputValue;
@Nullable
private final String changeOutputAddress;
private final byte[] takerMultiSigPubKey;
private final String takerPayoutAddressString;
private final PubKeyRing takerPubKeyRing;
private final PaymentAccountPayload takerPaymentAccountPayload;
private final String takerAccountId;
private final String takerFeeTxId;
private final List<NodeAddress> acceptedArbitratorNodeAddresses;
private final List<NodeAddress> acceptedMediatorNodeAddresses;
private final List<NodeAddress> acceptedRefundAgentNodeAddresses;
@Nullable
private final NodeAddress arbitratorNodeAddress;
private final NodeAddress mediatorNodeAddress;
private final NodeAddress refundAgentNodeAddress;
private final byte[] accountAgeWitnessSignatureOfOfferId;
private final long currentDate;
public InputsForDepositTxRequest(String tradeId,
NodeAddress senderNodeAddress,
long tradeAmount,
long tradePrice,
long txFee,
long takerFee,
List<RawTransactionInput> rawTransactionInputs,
long changeOutputValue,
@Nullable String changeOutputAddress,
byte[] takerMultiSigPubKey,
String takerPayoutAddressString,
PubKeyRing takerPubKeyRing,
PaymentAccountPayload takerPaymentAccountPayload,
String takerAccountId,
String takerFeeTxId,
List<NodeAddress> acceptedArbitratorNodeAddresses,
List<NodeAddress> acceptedMediatorNodeAddresses,
List<NodeAddress> acceptedRefundAgentNodeAddresses,
@Nullable NodeAddress arbitratorNodeAddress,
NodeAddress mediatorNodeAddress,
NodeAddress refundAgentNodeAddress,
String uid,
String messageVersion,
byte[] accountAgeWitnessSignatureOfOfferId,
long currentDate) {
super(messageVersion, tradeId, uid);
this.senderNodeAddress = senderNodeAddress;
this.tradeAmount = tradeAmount;
this.tradePrice = tradePrice;
this.txFee = txFee;
this.takerFee = takerFee;
this.rawTransactionInputs = rawTransactionInputs;
this.changeOutputValue = changeOutputValue;
this.changeOutputAddress = changeOutputAddress;
this.takerMultiSigPubKey = takerMultiSigPubKey;
this.takerPayoutAddressString = takerPayoutAddressString;
this.takerPubKeyRing = takerPubKeyRing;
this.takerPaymentAccountPayload = takerPaymentAccountPayload;
this.takerAccountId = takerAccountId;
this.takerFeeTxId = takerFeeTxId;
this.acceptedArbitratorNodeAddresses = acceptedArbitratorNodeAddresses;
this.acceptedMediatorNodeAddresses = acceptedMediatorNodeAddresses;
this.acceptedRefundAgentNodeAddresses = acceptedRefundAgentNodeAddresses;
this.arbitratorNodeAddress = arbitratorNodeAddress;
this.mediatorNodeAddress = mediatorNodeAddress;
this.refundAgentNodeAddress = refundAgentNodeAddress;
this.accountAgeWitnessSignatureOfOfferId = accountAgeWitnessSignatureOfOfferId;
this.currentDate = currentDate;
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
protobuf.InputsForDepositTxRequest.Builder builder = protobuf.InputsForDepositTxRequest.newBuilder()
.setTradeId(tradeId)
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
.setTradeAmount(tradeAmount)
.setTradePrice(tradePrice)
.setTxFee(txFee)
.setTakerFee(takerFee)
.addAllRawTransactionInputs(rawTransactionInputs.stream()
.map(RawTransactionInput::toProtoMessage).collect(Collectors.toList()))
.setChangeOutputValue(changeOutputValue)
.setTakerMultiSigPubKey(ByteString.copyFrom(takerMultiSigPubKey))
.setTakerPayoutAddressString(takerPayoutAddressString)
.setTakerPubKeyRing(takerPubKeyRing.toProtoMessage())
.setTakerPaymentAccountPayload((protobuf.PaymentAccountPayload) takerPaymentAccountPayload.toProtoMessage())
.setTakerAccountId(takerAccountId)
.setTakerFeeTxId(takerFeeTxId)
.addAllAcceptedArbitratorNodeAddresses(acceptedArbitratorNodeAddresses.stream()
.map(NodeAddress::toProtoMessage).collect(Collectors.toList()))
.addAllAcceptedMediatorNodeAddresses(acceptedMediatorNodeAddresses.stream()
.map(NodeAddress::toProtoMessage).collect(Collectors.toList()))
.addAllAcceptedRefundAgentNodeAddresses(acceptedRefundAgentNodeAddresses.stream()
.map(NodeAddress::toProtoMessage).collect(Collectors.toList()))
.setMediatorNodeAddress(mediatorNodeAddress.toProtoMessage())
.setRefundAgentNodeAddress(refundAgentNodeAddress.toProtoMessage())
.setUid(uid)
.setAccountAgeWitnessSignatureOfOfferId(ByteString.copyFrom(accountAgeWitnessSignatureOfOfferId))
.setCurrentDate(currentDate);
Optional.ofNullable(changeOutputAddress).ifPresent(builder::setChangeOutputAddress);
Optional.ofNullable(arbitratorNodeAddress).ifPresent(e -> builder.setArbitratorNodeAddress(arbitratorNodeAddress.toProtoMessage()));
return getNetworkEnvelopeBuilder().setInputsForDepositTxRequest(builder).build();
}
public static InputsForDepositTxRequest fromProto(protobuf.InputsForDepositTxRequest proto,
CoreProtoResolver coreProtoResolver,
String messageVersion) {
List<RawTransactionInput> rawTransactionInputs = proto.getRawTransactionInputsList().stream()
.map(rawTransactionInput -> new RawTransactionInput(rawTransactionInput.getIndex(),
rawTransactionInput.getParentTransaction().toByteArray(), rawTransactionInput.getValue()))
.collect(Collectors.toList());
List<NodeAddress> acceptedArbitratorNodeAddresses = proto.getAcceptedArbitratorNodeAddressesList().stream()
.map(NodeAddress::fromProto).collect(Collectors.toList());
List<NodeAddress> acceptedMediatorNodeAddresses = proto.getAcceptedMediatorNodeAddressesList().stream()
.map(NodeAddress::fromProto).collect(Collectors.toList());
List<NodeAddress> acceptedRefundAgentNodeAddresses = proto.getAcceptedRefundAgentNodeAddressesList().stream()
.map(NodeAddress::fromProto).collect(Collectors.toList());
return new InputsForDepositTxRequest(proto.getTradeId(),
NodeAddress.fromProto(proto.getSenderNodeAddress()),
proto.getTradeAmount(),
proto.getTradePrice(),
proto.getTxFee(),
proto.getTakerFee(),
rawTransactionInputs,
proto.getChangeOutputValue(),
ProtoUtil.stringOrNullFromProto(proto.getChangeOutputAddress()),
proto.getTakerMultiSigPubKey().toByteArray(),
proto.getTakerPayoutAddressString(),
PubKeyRing.fromProto(proto.getTakerPubKeyRing()),
coreProtoResolver.fromProto(proto.getTakerPaymentAccountPayload()),
proto.getTakerAccountId(),
proto.getTakerFeeTxId(),
acceptedArbitratorNodeAddresses,
acceptedMediatorNodeAddresses,
acceptedRefundAgentNodeAddresses,
NodeAddress.fromProto(proto.getArbitratorNodeAddress()),
NodeAddress.fromProto(proto.getMediatorNodeAddress()),
NodeAddress.fromProto(proto.getRefundAgentNodeAddress()),
proto.getUid(),
messageVersion,
ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfOfferId()),
proto.getCurrentDate());
}
@Override
public String toString() {
return "InputsForDepositTxRequest{" +
"\n senderNodeAddress=" + senderNodeAddress +
",\n tradeAmount=" + tradeAmount +
",\n tradePrice=" + tradePrice +
",\n txFee=" + txFee +
",\n takerFee=" + takerFee +
",\n rawTransactionInputs=" + rawTransactionInputs +
",\n changeOutputValue=" + changeOutputValue +
",\n changeOutputAddress='" + changeOutputAddress + '\'' +
",\n takerMultiSigPubKey=" + Utilities.bytesAsHexString(takerMultiSigPubKey) +
",\n takerPayoutAddressString='" + takerPayoutAddressString + '\'' +
",\n takerPubKeyRing=" + takerPubKeyRing +
",\n takerPaymentAccountPayload=" + takerPaymentAccountPayload +
",\n takerAccountId='" + takerAccountId + '\'' +
",\n takerFeeTxId='" + takerFeeTxId + '\'' +
",\n acceptedArbitratorNodeAddresses=" + acceptedArbitratorNodeAddresses +
",\n acceptedMediatorNodeAddresses=" + acceptedMediatorNodeAddresses +
",\n acceptedRefundAgentNodeAddresses=" + acceptedRefundAgentNodeAddresses +
",\n arbitratorNodeAddress=" + arbitratorNodeAddress +
",\n mediatorNodeAddress=" + mediatorNodeAddress +
",\n refundAgentNodeAddress=" + refundAgentNodeAddress +
",\n accountAgeWitnessSignatureOfOfferId=" + Utilities.bytesAsHexString(accountAgeWitnessSignatureOfOfferId) +
",\n currentDate=" + currentDate +
"\n} " + super.toString();
}
}

View File

@ -1,193 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.messages;
import bisq.core.btc.model.RawTransactionInput;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.proto.CoreProtoResolver;
import bisq.network.p2p.DirectMessage;
import bisq.network.p2p.NodeAddress;
import bisq.common.app.Version;
import bisq.common.proto.ProtoUtil;
import bisq.common.util.Utilities;
import com.google.protobuf.ByteString;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
import lombok.Value;
import javax.annotation.Nullable;
@EqualsAndHashCode(callSuper = true)
@Value
public final class InputsForDepositTxResponse extends TradeMessage implements DirectMessage {
private final PaymentAccountPayload makerPaymentAccountPayload;
private final String makerAccountId;
private final byte[] makerMultiSigPubKey;
private final String makerContractAsJson;
private final String makerContractSignature;
private final String makerPayoutAddressString;
private final byte[] preparedDepositTx;
private final List<RawTransactionInput> makerInputs;
private final NodeAddress senderNodeAddress;
// added in v 0.6. can be null if we trade with an older peer
@Nullable
private final byte[] accountAgeWitnessSignatureOfPreparedDepositTx;
private final long currentDate;
private final long lockTime;
public InputsForDepositTxResponse(String tradeId,
PaymentAccountPayload makerPaymentAccountPayload,
String makerAccountId,
byte[] makerMultiSigPubKey,
String makerContractAsJson,
String makerContractSignature,
String makerPayoutAddressString,
byte[] preparedDepositTx,
List<RawTransactionInput> makerInputs,
NodeAddress senderNodeAddress,
String uid,
@Nullable byte[] accountAgeWitnessSignatureOfPreparedDepositTx,
long currentDate,
long lockTime) {
this(tradeId,
makerPaymentAccountPayload,
makerAccountId,
makerMultiSigPubKey,
makerContractAsJson,
makerContractSignature,
makerPayoutAddressString,
preparedDepositTx,
makerInputs,
senderNodeAddress,
uid,
Version.getP2PMessageVersion(),
accountAgeWitnessSignatureOfPreparedDepositTx,
currentDate,
lockTime);
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
private InputsForDepositTxResponse(String tradeId,
PaymentAccountPayload makerPaymentAccountPayload,
String makerAccountId,
byte[] makerMultiSigPubKey,
String makerContractAsJson,
String makerContractSignature,
String makerPayoutAddressString,
byte[] preparedDepositTx,
List<RawTransactionInput> makerInputs,
NodeAddress senderNodeAddress,
String uid,
String messageVersion,
@Nullable byte[] accountAgeWitnessSignatureOfPreparedDepositTx,
long currentDate,
long lockTime) {
super(messageVersion, tradeId, uid);
this.makerPaymentAccountPayload = makerPaymentAccountPayload;
this.makerAccountId = makerAccountId;
this.makerMultiSigPubKey = makerMultiSigPubKey;
this.makerContractAsJson = makerContractAsJson;
this.makerContractSignature = makerContractSignature;
this.makerPayoutAddressString = makerPayoutAddressString;
this.preparedDepositTx = preparedDepositTx;
this.makerInputs = makerInputs;
this.senderNodeAddress = senderNodeAddress;
this.accountAgeWitnessSignatureOfPreparedDepositTx = accountAgeWitnessSignatureOfPreparedDepositTx;
this.currentDate = currentDate;
this.lockTime = lockTime;
}
@Override
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
final protobuf.InputsForDepositTxResponse.Builder builder = protobuf.InputsForDepositTxResponse.newBuilder()
.setTradeId(tradeId)
.setMakerPaymentAccountPayload((protobuf.PaymentAccountPayload) makerPaymentAccountPayload.toProtoMessage())
.setMakerAccountId(makerAccountId)
.setMakerMultiSigPubKey(ByteString.copyFrom(makerMultiSigPubKey))
.setMakerContractAsJson(makerContractAsJson)
.setMakerContractSignature(makerContractSignature)
.setMakerPayoutAddressString(makerPayoutAddressString)
.setPreparedDepositTx(ByteString.copyFrom(preparedDepositTx))
.addAllMakerInputs(makerInputs.stream().map(RawTransactionInput::toProtoMessage).collect(Collectors.toList()))
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
.setUid(uid)
.setLockTime(lockTime);
Optional.ofNullable(accountAgeWitnessSignatureOfPreparedDepositTx).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfPreparedDepositTx(ByteString.copyFrom(e)));
builder.setCurrentDate(currentDate);
return getNetworkEnvelopeBuilder()
.setInputsForDepositTxResponse(builder)
.build();
}
public static InputsForDepositTxResponse fromProto(protobuf.InputsForDepositTxResponse proto, CoreProtoResolver coreProtoResolver, String messageVersion) {
List<RawTransactionInput> makerInputs = proto.getMakerInputsList().stream()
.map(RawTransactionInput::fromProto)
.collect(Collectors.toList());
return new InputsForDepositTxResponse(proto.getTradeId(),
coreProtoResolver.fromProto(proto.getMakerPaymentAccountPayload()),
proto.getMakerAccountId(),
proto.getMakerMultiSigPubKey().toByteArray(),
proto.getMakerContractAsJson(),
proto.getMakerContractSignature(),
proto.getMakerPayoutAddressString(),
proto.getPreparedDepositTx().toByteArray(),
makerInputs,
NodeAddress.fromProto(proto.getSenderNodeAddress()),
proto.getUid(),
messageVersion,
ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfPreparedDepositTx()),
proto.getCurrentDate(),
proto.getLockTime());
}
@Override
public String toString() {
return "InputsForDepositTxResponse{" +
"\n makerPaymentAccountPayload=" + makerPaymentAccountPayload +
",\n makerAccountId='" + makerAccountId + '\'' +
",\n makerMultiSigPubKey=" + Utilities.bytesAsHexString(makerMultiSigPubKey) +
",\n makerContractAsJson='" + makerContractAsJson + '\'' +
",\n makerContractSignature='" + makerContractSignature + '\'' +
",\n makerPayoutAddressString='" + makerPayoutAddressString + '\'' +
",\n preparedDepositTx=" + Utilities.bytesAsHexString(preparedDepositTx) +
",\n makerInputs=" + makerInputs +
",\n senderNodeAddress=" + senderNodeAddress +
",\n uid='" + uid + '\'' +
",\n accountAgeWitnessSignatureOfPreparedDepositTx=" + Utilities.bytesAsHexString(accountAgeWitnessSignatureOfPreparedDepositTx) +
",\n currentDate=" + new Date(currentDate) +
",\n lockTime=" + lockTime +
"\n} " + super.toString();
}
}

View File

@ -1,76 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.messages;
import bisq.network.p2p.NodeAddress;
import bisq.common.app.Version;
import lombok.EqualsAndHashCode;
import lombok.Value;
@EqualsAndHashCode(callSuper = true)
@Value
public final class PeerPublishedDelayedPayoutTxMessage extends TradeMailboxMessage {
private final NodeAddress senderNodeAddress;
public PeerPublishedDelayedPayoutTxMessage(String uid,
String tradeId,
NodeAddress senderNodeAddress) {
this(Version.getP2PMessageVersion(),
uid,
tradeId,
senderNodeAddress);
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
private PeerPublishedDelayedPayoutTxMessage(String messageVersion,
String uid,
String tradeId,
NodeAddress senderNodeAddress) {
super(messageVersion, tradeId, uid);
this.senderNodeAddress = senderNodeAddress;
}
@Override
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
final protobuf.PeerPublishedDelayedPayoutTxMessage.Builder builder = protobuf.PeerPublishedDelayedPayoutTxMessage.newBuilder();
builder.setUid(uid)
.setTradeId(tradeId)
.setSenderNodeAddress(senderNodeAddress.toProtoMessage());
return getNetworkEnvelopeBuilder().setPeerPublishedDelayedPayoutTxMessage(builder).build();
}
public static PeerPublishedDelayedPayoutTxMessage fromProto(protobuf.PeerPublishedDelayedPayoutTxMessage proto, String messageVersion) {
return new PeerPublishedDelayedPayoutTxMessage(messageVersion,
proto.getUid(),
proto.getTradeId(),
NodeAddress.fromProto(proto.getSenderNodeAddress()));
}
@Override
public String toString() {
return "PeerPublishedDelayedPayoutTxMessage{" +
"\n senderNodeAddress=" + senderNodeAddress +
"\n} " + super.toString();
}
}

View File

@ -75,7 +75,7 @@ public class ArbitratorProtocol extends DisputeProtocol {
ArbitratorProcessesDepositRequest.class)
.using(new TradeTaskRunner(trade,
() -> {
if (trade.getState() == Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TX) {
if (trade.getState() == Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS) {
stopTimeout();
this.errorMessageHandler = null;
}

View File

@ -19,26 +19,16 @@ package bisq.core.trade.protocol;
import bisq.core.trade.BuyerAsMakerTrade;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest;
import bisq.core.trade.messages.DepositResponse;
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
import bisq.core.trade.messages.InitMultisigRequest;
import bisq.core.trade.messages.InitTradeRequest;
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
import bisq.core.trade.messages.PaymentReceivedMessage;
import bisq.core.trade.messages.SignContractRequest;
import bisq.core.trade.messages.SignContractResponse;
import bisq.core.trade.protocol.tasks.MakerSendsInitTradeRequestIfUnreserved;
import bisq.core.trade.protocol.tasks.ProcessInitTradeRequest;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.core.trade.protocol.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse;
import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.maker.MaybeRemoveOpenOffer;
import bisq.core.trade.protocol.tasks.maker.MakerSendsInitTradeRequestIfUnreserved;
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
import bisq.network.p2p.NodeAddress;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
@ -134,37 +124,4 @@ public class BuyerAsMakerProtocol extends BuyerProtocol implements MakerProtocol
protected void handle(PaymentReceivedMessage message, NodeAddress peer) {
super.handle(message, peer);
}
@Override
protected Class<? extends TradeTask> getVerifyPeersFeePaymentClass() {
return MakerVerifyTakerFeePayment.class;
}
// TODO (woodser): remove or ignore any unsupported requests
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming messages Take offer process
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) {
expect(phase(Trade.Phase.TAKER_FEE_PUBLISHED)
.with(message)
.from(peer))
.setup(tasks(
MaybeRemoveOpenOffer.class,
BuyerProcessDelayedPayoutTxSignatureRequest.class,
BuyerVerifiesPreparedDelayedPayoutTx.class,
BuyerSignsDelayedPayoutTx.class,
BuyerFinalizesDelayedPayoutTx.class,
BuyerSendsDelayedPayoutTxSignatureResponse.class)
.withTimeout(60))
.executeTasks(true);
}
// We keep the handler here in as well to make it more transparent which messages we expect
@Override
protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) {
super.handle(message, peer);
}
}

View File

@ -22,32 +22,14 @@ import bisq.core.offer.Offer;
import bisq.core.trade.BuyerAsTakerTrade;
import bisq.core.trade.Trade;
import bisq.core.trade.handlers.TradeResultHandler;
import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest;
import bisq.core.trade.messages.DepositResponse;
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
import bisq.core.trade.messages.InitMultisigRequest;
import bisq.core.trade.messages.InputsForDepositTxResponse;
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
import bisq.core.trade.messages.PaymentReceivedMessage;
import bisq.core.trade.messages.SignContractRequest;
import bisq.core.trade.messages.SignContractResponse;
import bisq.core.trade.messages.TradeMessage;
import bisq.core.trade.protocol.tasks.ApplyFilter;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
import bisq.core.trade.protocol.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse;
import bisq.core.trade.protocol.tasks.buyer.BuyerSetupDepositTxListener;
import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSendsDepositTxMessage;
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx;
import bisq.core.trade.protocol.tasks.taker.TakerProcessesInputsForDepositTxResponse;
import bisq.core.trade.protocol.tasks.taker.TakerPublishFeeTx;
import bisq.core.trade.protocol.tasks.taker.TakerReservesTradeFunds;
import bisq.core.trade.protocol.tasks.taker.TakerSendsInitTradeRequestToArbitrator;
import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment;
import bisq.network.p2p.NodeAddress;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
@ -56,7 +38,6 @@ import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
// TODO (woodser): remove unused request handling
@Slf4j
public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol {
@ -159,57 +140,5 @@ public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol
@Override
protected void onTradeMessage(TradeMessage message, NodeAddress peer) {
super.onTradeMessage(message, peer);
if (message instanceof InputsForDepositTxResponse) {
handle((InputsForDepositTxResponse) message, peer);
}
}
@Override
protected Class<? extends TradeTask> getVerifyPeersFeePaymentClass() {
return TakerVerifyMakerFeePayment.class;
}
// TODO (woodser): remove unused
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming messages Take offer process
///////////////////////////////////////////////////////////////////////////////////////////
private void handle(InputsForDepositTxResponse message, NodeAddress peer) {
expect(phase(Trade.Phase.INIT)
.with(message)
.from(peer))
.setup(tasks(TakerProcessesInputsForDepositTxResponse.class,
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
//TakerVerifyAndSignContract.class,
TakerPublishFeeTx.class,
BuyerAsTakerSignsDepositTx.class,
BuyerSetupDepositTxListener.class,
BuyerAsTakerSendsDepositTxMessage.class)
.withTimeout(60))
.executeTasks(true);
}
@Override
protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) {
expect(phase(Trade.Phase.TAKER_FEE_PUBLISHED)
.with(message)
.from(peer))
.setup(tasks(
BuyerProcessDelayedPayoutTxSignatureRequest.class,
BuyerVerifiesPreparedDelayedPayoutTx.class,
BuyerSignsDelayedPayoutTx.class,
BuyerFinalizesDelayedPayoutTx.class,
BuyerSendsDelayedPayoutTxSignatureResponse.class)
.withTimeout(60))
.executeTasks(true);
}
// We keep the handler here in as well to make it more transparent which messages we expect
@Override
protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) {
super.handle(message, peer);
}
}

View File

@ -19,17 +19,14 @@ package bisq.core.trade.protocol;
import bisq.core.trade.BuyerTrade;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest;
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
import bisq.core.trade.messages.PaymentReceivedMessage;
import bisq.core.trade.messages.TradeMessage;
import bisq.core.trade.protocol.tasks.ApplyFilter;
import bisq.core.trade.protocol.tasks.BuyerPreparesPaymentSentMessage;
import bisq.core.trade.protocol.tasks.BuyerProcessesPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.BuyerSendsPaymentSentMessage;
import bisq.core.trade.protocol.tasks.BuyerSetupPayoutTxListener;
import bisq.core.trade.protocol.tasks.SetupDepositTxsListener;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.core.trade.protocol.tasks.buyer.BuyerPreparesPaymentSentMessage;
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessesPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.buyer.BuyerSendsPaymentSentMessage;
import bisq.core.trade.protocol.tasks.buyer.BuyerSetupPayoutTxListener;
import bisq.core.util.Validator;
import bisq.network.p2p.NodeAddress;
import bisq.common.handlers.ErrorMessageHandler;
@ -77,49 +74,11 @@ public abstract class BuyerProtocol extends DisputeProtocol {
@Override
public void onMailboxMessage(TradeMessage message, NodeAddress peer) {
super.onMailboxMessage(message, peer);
if (message instanceof DepositTxAndDelayedPayoutTxMessage) {
handle((DepositTxAndDelayedPayoutTxMessage) message, peer);
} else if (message instanceof PaymentReceivedMessage) {
if (message instanceof PaymentReceivedMessage) {
handle((PaymentReceivedMessage) message, peer);
}
}
protected abstract void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer);
// The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can
// be also with from the network once published.
// Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol.
// We do not support mailbox message handling during the take offer process as it is expected that both peers
// are online.
// For backward compatibility and extra resilience we still keep DepositTxAndDelayedPayoutTxMessage as a
// mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again
// in the hope to reach the buyer directly.
protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) {
// expect(anyPhase(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED)
// .with(message)
// .from(peer)
// .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null,
// () -> {
// log.warn("We with a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " +
// "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " +
// "arrive and the peer repeats sending us the message. We send another ACK msg.");
// stopTimeout();
// sendAckMessage(message, true, null);
// removeMailboxMessageAfterProcessing(message);
// }))
// .setup(tasks(BuyerProcessDepositTxAndDelayedPayoutTxMessage.class,
// BuyerVerifiesFinalDelayedPayoutTx.class)
// .using(new TradeTaskRunner(trade,
// () -> {
// stopTimeout();
// handleTaskRunnerSuccess(message);
// },
// errorMessage -> handleTaskRunnerFault(message, errorMessage))))
// .run(() -> processModel.witnessDebugLog(trade))
// .executeTasks();
}
///////////////////////////////////////////////////////////////////////////////////////////
// User interaction
///////////////////////////////////////////////////////////////////////////////////////////
@ -135,7 +94,6 @@ public abstract class BuyerProtocol extends DisputeProtocol {
.with(event)
.preCondition(trade.confirmPermitted()))
.setup(tasks(ApplyFilter.class,
getVerifyPeersFeePaymentClass(),
//UpdateMultisigWithTradingPeer.class, // TODO (woodser): can use this to test protocol with updated multisig from peer. peer should attempt to send updated multisig hex earlier as part of protocol. cannot use with countdown latch because response comes back in a separate thread and blocks on trade
BuyerPreparesPaymentSentMessage.class,
//BuyerSetupPayoutTxListener.class,
@ -170,7 +128,6 @@ public abstract class BuyerProtocol extends DisputeProtocol {
.with(message)
.from(peer))
.setup(tasks(
getVerifyPeersFeePaymentClass(),
BuyerProcessesPaymentReceivedMessage.class)
.using(new TradeTaskRunner(trade,
() -> {
@ -192,15 +149,8 @@ public abstract class BuyerProtocol extends DisputeProtocol {
@Override
protected void onTradeMessage(TradeMessage message, NodeAddress peer) {
super.onTradeMessage(message, peer);
if (message instanceof DelayedPayoutTxSignatureRequest) {
handle((DelayedPayoutTxSignatureRequest) message, peer);
} else if (message instanceof DepositTxAndDelayedPayoutTxMessage) {
handle((DepositTxAndDelayedPayoutTxMessage) message, peer);
} else if (message instanceof PaymentReceivedMessage) {
if (message instanceof PaymentReceivedMessage) {
handle((PaymentReceivedMessage) message, peer);
}
}
abstract protected Class<? extends TradeTask> getVerifyPeersFeePaymentClass();
}

View File

@ -20,11 +20,8 @@ package bisq.core.trade.protocol;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage;
import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage;
import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage;
import bisq.core.trade.messages.TradeMessage;
import bisq.core.trade.protocol.tasks.ApplyFilter;
import bisq.core.trade.protocol.tasks.ProcessPeerPublishedDelayedPayoutTxMessage;
import bisq.core.trade.protocol.tasks.mediation.BroadcastMediatedPayoutTx;
import bisq.core.trade.protocol.tasks.mediation.FinalizeMediatedPayoutTx;
import bisq.core.trade.protocol.tasks.mediation.ProcessMediatedPayoutSignatureMessage;
import bisq.core.trade.protocol.tasks.mediation.ProcessMediatedPayoutTxPublishedMessage;
@ -97,7 +94,6 @@ public abstract class DisputeProtocol extends TradeProtocol {
.setup(tasks(ApplyFilter.class,
SignMediatedPayoutTx.class,
FinalizeMediatedPayoutTx.class,
BroadcastMediatedPayoutTx.class,
SendMediatedPayoutTxPublishedMessage.class)
.using(new TradeTaskRunner(trade,
() -> {
@ -162,21 +158,6 @@ public abstract class DisputeProtocol extends TradeProtocol {
// }
///////////////////////////////////////////////////////////////////////////////////////////
// Peer has published the delayed payout tx
///////////////////////////////////////////////////////////////////////////////////////////
private void handle(PeerPublishedDelayedPayoutTxMessage message, NodeAddress peer) {
expect(anyPhase(Trade.Phase.DEPOSIT_UNLOCKED,
Trade.Phase.PAYMENT_SENT,
Trade.Phase.PAYMENT_RECEIVED)
.with(message)
.from(peer))
.setup(tasks(ProcessPeerPublishedDelayedPayoutTxMessage.class))
.executeTasks();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Dispatcher
///////////////////////////////////////////////////////////////////////////////////////////
@ -187,8 +168,6 @@ public abstract class DisputeProtocol extends TradeProtocol {
handle((MediatedPayoutTxSignatureMessage) message, peer);
} else if (message instanceof MediatedPayoutTxPublishedMessage) {
handle((MediatedPayoutTxPublishedMessage) message, peer);
} else if (message instanceof PeerPublishedDelayedPayoutTxMessage) {
handle((PeerPublishedDelayedPayoutTxMessage) message, peer);
}
}
@ -199,8 +178,6 @@ public abstract class DisputeProtocol extends TradeProtocol {
handle((MediatedPayoutTxSignatureMessage) message, peer);
} else if (message instanceof MediatedPayoutTxPublishedMessage) {
handle((MediatedPayoutTxPublishedMessage) message, peer);
} else if (message instanceof PeerPublishedDelayedPayoutTxMessage) {
handle((PeerPublishedDelayedPayoutTxMessage) message, peer);
}
}
}

View File

@ -24,21 +24,12 @@ import bisq.core.trade.messages.PaymentSentMessage;
import bisq.core.trade.messages.SignContractRequest;
import bisq.core.trade.messages.SignContractResponse;
import bisq.core.trade.messages.DepositResponse;
import bisq.core.trade.messages.DepositTxMessage;
import bisq.core.trade.messages.InitMultisigRequest;
import bisq.core.trade.messages.InitTradeRequest;
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
import bisq.core.trade.messages.TradeMessage;
import bisq.core.trade.protocol.tasks.MakerSendsInitTradeRequestIfUnreserved;
import bisq.core.trade.protocol.tasks.ProcessInitTradeRequest;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.core.trade.protocol.tasks.maker.MaybeRemoveOpenOffer;
import bisq.core.trade.protocol.tasks.maker.MakerSendsInitTradeRequestIfUnreserved;
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.seller.SellerSendDelayedPayoutTxSignatureRequest;
import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerFinalizesDepositTx;
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerProcessDepositTxMessage;
import bisq.network.p2p.NodeAddress;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
@ -132,42 +123,9 @@ public class SellerAsMakerProtocol extends SellerProtocol implements MakerProtoc
@Override
protected void onTradeMessage(TradeMessage message, NodeAddress peer) {
super.onTradeMessage(message, peer);
log.info("Received {} from {} with tradeId {} and uid {}",
message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid());
if (message instanceof DepositTxMessage) {
handle((DepositTxMessage) message, peer);
}
log.info("Received {} from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid());
}
@Override
protected Class<? extends TradeTask> getVerifyPeersFeePaymentClass() {
return MakerVerifyTakerFeePayment.class;
}
// TODO (woodser): remove unused
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming messages Take offer process
///////////////////////////////////////////////////////////////////////////////////////////
protected void handle(DepositTxMessage message, NodeAddress peer) {
expect(phase(Trade.Phase.TAKER_FEE_PUBLISHED)
.with(message)
.from(peer))
.setup(tasks(
MaybeRemoveOpenOffer.class,
SellerAsMakerProcessDepositTxMessage.class,
SellerAsMakerFinalizesDepositTx.class,
SellerCreatesDelayedPayoutTx.class,
SellerSignsDelayedPayoutTx.class,
SellerSendDelayedPayoutTxSignatureRequest.class)
.withTimeout(60))
.executeTasks(true);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message when buyer has clicked payment started button
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -27,22 +27,9 @@ import bisq.core.trade.messages.SignContractRequest;
import bisq.core.trade.messages.SignContractResponse;
import bisq.core.trade.messages.DepositResponse;
import bisq.core.trade.messages.InitMultisigRequest;
import bisq.core.trade.messages.InputsForDepositTxResponse;
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
import bisq.core.trade.messages.TradeMessage;
import bisq.core.trade.protocol.tasks.ApplyFilter;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.seller.SellerSendDelayedPayoutTxSignatureRequest;
import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerSignsDepositTx;
import bisq.core.trade.protocol.tasks.taker.TakerProcessesInputsForDepositTxResponse;
import bisq.core.trade.protocol.tasks.taker.TakerPublishFeeTx;
import bisq.core.trade.protocol.tasks.taker.TakerReservesTradeFunds;
import bisq.core.trade.protocol.tasks.taker.TakerSendsInitTradeRequestToArbitrator;
import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment;
import bisq.network.p2p.NodeAddress;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
@ -152,41 +139,6 @@ public class SellerAsTakerProtocol extends SellerProtocol implements TakerProtoc
@Override
protected void onTradeMessage(TradeMessage message, NodeAddress peer) {
super.onTradeMessage(message, peer);
log.info("Received {} from {} with tradeId {} and uid {}",
message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid());
if (message instanceof InputsForDepositTxResponse) {
handle((InputsForDepositTxResponse) message, peer);
}
}
@Override
protected Class<? extends TradeTask> getVerifyPeersFeePaymentClass() {
return TakerVerifyMakerFeePayment.class;
}
// TODO (woodser): remove unused calls and classes
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming messages Take offer process
///////////////////////////////////////////////////////////////////////////////////////////
private void handle(InputsForDepositTxResponse message, NodeAddress peer) {
expect(phase(Trade.Phase.INIT)
.with(message)
.from(peer))
.setup(tasks(
TakerProcessesInputsForDepositTxResponse.class,
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
//TakerVerifyAndSignContract.class,
TakerPublishFeeTx.class,
SellerAsTakerSignsDepositTx.class,
SellerCreatesDelayedPayoutTx.class,
SellerSignsDelayedPayoutTx.class,
SellerSendDelayedPayoutTxSignatureRequest.class)
.withTimeout(60))
.executeTasks(true);
log.info("Received {} from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid());
}
}

View File

@ -23,12 +23,10 @@ import bisq.core.trade.messages.PaymentSentMessage;
import bisq.core.trade.messages.TradeMessage;
import bisq.core.trade.protocol.BuyerProtocol.BuyerEvent;
import bisq.core.trade.protocol.tasks.ApplyFilter;
import bisq.core.trade.protocol.tasks.SellerPreparesPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.SellerProcessesPaymentSentMessage;
import bisq.core.trade.protocol.tasks.SellerSendsPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.SetupDepositTxsListener;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.core.trade.protocol.tasks.seller.SellerProcessesPaymentSentMessage;
import bisq.core.trade.protocol.tasks.seller.SellerSendsPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.seller.SellerPreparesPaymentReceivedMessage;
import bisq.network.p2p.NodeAddress;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
@ -100,9 +98,8 @@ public abstract class SellerProtocol extends DisputeProtocol {
removeMailboxMessageAfterProcessing(message);
}))
.setup(tasks(
SellerProcessesPaymentSentMessage.class,
ApplyFilter.class,
getVerifyPeersFeePaymentClass())
SellerProcessesPaymentSentMessage.class)
.using(new TradeTaskRunner(trade,
() -> {
stopTimeout();
@ -134,7 +131,6 @@ public abstract class SellerProtocol extends DisputeProtocol {
.preCondition(trade.confirmPermitted()))
.setup(tasks(
ApplyFilter.class,
getVerifyPeersFeePaymentClass(),
SellerPreparesPaymentReceivedMessage.class,
SellerSendsPaymentReceivedMessage.class)
.using(new TradeTaskRunner(trade, () -> {
@ -159,7 +155,4 @@ public abstract class SellerProtocol extends DisputeProtocol {
handle((PaymentSentMessage) message, peer);
}
}
abstract protected Class<? extends TradeTask> getVerifyPeersFeePaymentClass();
}

View File

@ -15,7 +15,7 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.taker;
package bisq.core.trade.protocol;
import bisq.common.taskrunner.TaskRunner;
import bisq.core.btc.model.XmrAddressEntry;

View File

@ -15,7 +15,7 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.taker;
package bisq.core.trade.protocol;
import bisq.core.support.dispute.arbitration.arbitrator.Arbitrator;
import bisq.core.trade.Trade;

View File

@ -15,7 +15,7 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.taker;
package bisq.core.trade.protocol;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;

View File

@ -24,13 +24,13 @@ import bisq.core.trade.TradeUtils;
import bisq.core.trade.handlers.TradeResultHandler;
import bisq.core.trade.messages.PaymentSentMessage;
import bisq.core.trade.messages.DepositResponse;
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
import bisq.core.trade.messages.InitMultisigRequest;
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
import bisq.core.trade.messages.SignContractRequest;
import bisq.core.trade.messages.SignContractResponse;
import bisq.core.trade.messages.TradeMessage;
import bisq.core.trade.messages.UpdateMultisigRequest;
import bisq.core.trade.protocol.tasks.MaybeRemoveOpenOffer;
import bisq.core.trade.protocol.tasks.MaybeSendSignContractRequest;
import bisq.core.trade.protocol.tasks.ProcessDepositResponse;
import bisq.core.trade.protocol.tasks.ProcessInitMultisigRequest;
@ -38,7 +38,6 @@ import bisq.core.trade.protocol.tasks.ProcessPaymentAccountPayloadRequest;
import bisq.core.trade.protocol.tasks.ProcessSignContractRequest;
import bisq.core.trade.protocol.tasks.ProcessSignContractResponse;
import bisq.core.trade.protocol.tasks.ProcessUpdateMultisigRequest;
import bisq.core.trade.protocol.tasks.maker.MaybeRemoveOpenOffer;
import bisq.core.util.Validator;
import bisq.network.p2p.AckMessage;
@ -324,7 +323,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
latchTrade();
Validator.checkTradeId(processModel.getOfferId(), response);
processModel.setTradeMessage(response);
expect(state(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST)
expect(state(Trade.State.SENT_PUBLISH_DEPOSIT_TX_REQUEST)
.with(response)
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
.setup(tasks(
@ -348,11 +347,11 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
System.out.println(getClass().getCanonicalName() + ".handlePaymentAccountPayloadRequest()");
synchronized (trade) {
Validator.checkTradeId(processModel.getOfferId(), request);
if (trade.getState() == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) {
if (trade.getState() == Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS) {
latchTrade();
Validator.checkTradeId(processModel.getOfferId(), request);
processModel.setTradeMessage(request);
expect(state(Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG)
expect(state(Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS)
.with(request)
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
.setup(tasks(
@ -374,7 +373,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
awaitTradeLatch();
} else {
EasyBind.subscribe(trade.stateProperty(), state -> {
if (state == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) new Thread(() -> handlePaymentAccountPayloadRequest(request, sender)).start(); // process notification without trade lock
if (state == Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS) new Thread(() -> handlePaymentAccountPayloadRequest(request, sender)).start(); // process notification without trade lock
});
}
}
@ -459,8 +458,6 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
// TODO (woodser): add AckMessage for InitTradeRequest and support automatic re-send ?
if (ackMessage.getSourceMsgClassName().equals(PaymentSentMessage.class.getSimpleName())) {
processModel.setPaymentStartedAckMessage(ackMessage);
} else if (ackMessage.getSourceMsgClassName().equals(DepositTxAndDelayedPayoutTxMessage.class.getSimpleName())) {
processModel.setDepositTxSentAckMessage(ackMessage);
}
if (ackMessage.isSuccess()) {

View File

@ -113,7 +113,7 @@ public class ArbitratorProcessesDepositRequest extends TradeTask {
// update trade state
log.info("Arbitrator submitted deposit txs for trade " + trade.getId());
trade.setState(Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TX);
trade.setState(Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS);
// create deposit response
DepositResponse response = new DepositResponse(

View File

@ -1,76 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks;
import bisq.core.trade.Trade;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
import monero.wallet.model.MoneroTxWallet;
@Slf4j
public abstract class BroadcastPayoutTx extends TradeTask {
public BroadcastPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
protected abstract void setState();
@Override
protected void run() {
try {
runInterceptHook();
if (true) throw new RuntimeException("BroadcastPayoutTx not implemented for xmr");
MoneroTxWallet payoutTx = trade.getPayoutTx();
checkNotNull(payoutTx, "payoutTx must not be null");
if (payoutTx.isRelayed()) {
log.debug("payoutTx was already published");
setState();
complete();
} else {
try {
processModel.getProvider().getXmrWalletService().getWallet().relayTx(payoutTx);
if (!completed) {
log.debug("BroadcastTx succeeded. Transaction:" + payoutTx);
setState();
complete();
} else {
log.warn("We got the onSuccess callback called after the timeout has been triggered a complete().");
}
} catch (Exception e) {
if (!completed) {
log.error("BroadcastTx failed. Error:" + e.getMessage());
failed(e);
} else {
log.warn("We got the onFailure callback called after the timeout has been triggered a complete().");
}
}
}
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -15,12 +15,10 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
package bisq.core.trade.protocol.tasks;
import bisq.core.btc.wallet.XmrWalletService;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import com.google.common.base.Preconditions;

View File

@ -15,13 +15,12 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
package bisq.core.trade.protocol.tasks;
import bisq.core.account.sign.SignedWitness;
import bisq.core.btc.wallet.XmrWalletService;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.PaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.core.util.Validator;
import bisq.common.taskrunner.TaskRunner;

View File

@ -15,7 +15,7 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
package bisq.core.trade.protocol.tasks;
import bisq.core.btc.model.XmrAddressEntry;
import bisq.core.btc.wallet.XmrWalletService;
@ -24,8 +24,6 @@ import bisq.core.trade.Trade;
import bisq.core.trade.messages.PaymentSentMessage;
import bisq.core.trade.messages.TradeMailboxMessage;
import bisq.core.trade.messages.TradeMessage;
import bisq.core.trade.protocol.tasks.SendMailboxMessageTask;
import bisq.common.Timer;
import bisq.common.UserThread;
import bisq.common.taskrunner.TaskRunner;

View File

@ -15,12 +15,10 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
package bisq.core.trade.protocol.tasks;
import bisq.core.btc.listeners.AddressConfidenceListener;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import org.fxmisc.easybind.Subscription;

View File

@ -15,11 +15,9 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
package bisq.core.trade.protocol.tasks;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.SetupPayoutTxListener;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;

View File

@ -15,14 +15,12 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.maker;
package bisq.core.trade.protocol.tasks;
import bisq.core.btc.model.XmrAddressEntry;
import bisq.core.offer.Offer;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.InitTradeRequest;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.network.p2p.SendDirectMessageListener;
import bisq.common.app.Version;

View File

@ -15,12 +15,10 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.maker;
package bisq.core.trade.protocol.tasks;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.config.Config;
import bisq.common.taskrunner.TaskRunner;

View File

@ -15,12 +15,10 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.maker;
package bisq.core.trade.protocol.tasks;
import bisq.core.trade.MakerTrade;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;

View File

@ -41,7 +41,7 @@ public class ProcessDepositResponse extends TradeTask {
runInterceptHook();
// arbitrator has broadcast deposit txs
trade.setState(Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG); // TODO (woodser): maker and taker?
trade.setState(Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS);
// set payment account payload
trade.getSelf().setPaymentAccountPayload(processModel.getPaymentAccountPayload(trade));

View File

@ -1,56 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks;
import bisq.core.trade.Trade;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ProcessPeerPublishedDelayedPayoutTxMessage extends TradeTask {
public ProcessPeerPublishedDelayedPayoutTxMessage(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
throw new RuntimeException("XMR adaptation does not support delayed payout tx");
// PeerPublishedDelayedPayoutTxMessage message = (PeerPublishedDelayedPayoutTxMessage) processModel.getTradeMessage();
// Validator.checkTradeId(processModel.getOfferId(), message);
// checkNotNull(message);
//
// // update to the latest peer address of our peer if the message is correct
// trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
//
// // We add the tx to our wallet.
// Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx());
// WalletService.maybeAddSelfTxToWallet(delayedPayoutTx, processModel.getBtcWalletService().getWallet());
//
// processModel.getTradeManager().requestPersistence();
//
// complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -88,7 +88,7 @@ public class ProcessSignContractResponse extends TradeTask {
@Override
public void onArrived() {
log.info("{} arrived: arbitrator={}; offerId={}; uid={}", request.getClass().getSimpleName(), trade.getArbitratorNodeAddress(), trade.getId(), request.getUid());
trade.setState(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST); // TODO: rename to DEPOSIT_REQUESTED
trade.setState(Trade.State.SENT_PUBLISH_DEPOSIT_TX_REQUEST); // TODO: rename to DEPOSIT_REQUESTED
processModel.getTradeManager().requestPersistence();
complete();
}

View File

@ -15,11 +15,9 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
package bisq.core.trade.protocol.tasks;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;

View File

@ -15,7 +15,7 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
package bisq.core.trade.protocol.tasks;
import static com.google.common.base.Preconditions.checkNotNull;
@ -23,7 +23,6 @@ import bisq.common.taskrunner.TaskRunner;
import bisq.core.btc.wallet.XmrWalletService;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.PaymentSentMessage;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.core.util.Validator;
import lombok.extern.slf4j.Slf4j;
import monero.wallet.MoneroWallet;

View File

@ -15,11 +15,9 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
package bisq.core.trade.protocol.tasks;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;

View File

@ -15,11 +15,9 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
package bisq.core.trade.protocol.tasks;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;

View File

@ -15,15 +15,13 @@
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
package bisq.core.trade.protocol.tasks;
import bisq.core.account.sign.SignedWitness;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.PaymentReceivedMessage;
import bisq.core.trade.messages.TradeMailboxMessage;
import bisq.core.trade.protocol.tasks.SendMailboxMessageTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.EqualsAndHashCode;

View File

@ -1,65 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.arbitration;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class PublishedDelayedPayoutTx extends TradeTask {
public PublishedDelayedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
throw new RuntimeException("PublishedDelayedPayoutTx not implemented for XMR");
// try {
// runInterceptHook();
//
// Transaction delayedPayoutTx = trade.getDelayedPayoutTx();
// BtcWalletService btcWalletService = processModel.getBtcWalletService();
//
// // We have spent the funds from the deposit tx with the delayedPayoutTx
// btcWalletService.resetCoinLockedInMultiSigAddressEntry(trade.getId());
// // We might receive funds on AddressEntry.Context.TRADE_PAYOUT so we don't swap that
//
// Transaction committedDelayedPayoutTx = WalletService.maybeAddSelfTxToWallet(delayedPayoutTx, btcWalletService.getWallet());
//
// processModel.getTradeWalletService().broadcastTx(committedDelayedPayoutTx, new TxBroadcaster.Callback() {
// @Override
// public void onSuccess(Transaction transaction) {
// log.info("publishDelayedPayoutTx onSuccess " + transaction);
// complete();
// }
//
// @Override
// public void onFailure(TxBroadcastException exception) {
// log.error("publishDelayedPayoutTx onFailure", exception);
// failed(exception.toString());
// }
// });
// } catch (Throwable t) {
// failed(t);
// }
}
}

View File

@ -1,71 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.arbitration;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage;
import bisq.core.trade.messages.TradeMailboxMessage;
import bisq.core.trade.protocol.tasks.SendMailboxMessageTask;
import bisq.common.taskrunner.TaskRunner;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SendPeerPublishedDelayedPayoutTxMessage extends SendMailboxMessageTask {
public SendPeerPublishedDelayedPayoutTxMessage(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected TradeMailboxMessage getTradeMailboxMessage(String id) {
return new PeerPublishedDelayedPayoutTxMessage(UUID.randomUUID().toString(),
trade.getId(),
trade.getTradingPeerNodeAddress());
}
@Override
protected void setStateSent() {
}
@Override
protected void setStateArrived() {
}
@Override
protected void setStateStoredInMailbox() {
}
@Override
protected void setStateFault() {
}
@Override
protected void run() {
try {
runInterceptHook();
super.run();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,61 +0,0 @@
package bisq.core.trade.protocol.tasks.buyer;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import bisq.common.util.Utilities;
import org.bitcoinj.core.Transaction;
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 BuyerFinalizesDelayedPayoutTx extends TradeTask {
public BuyerFinalizesDelayedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
BtcWalletService btcWalletService = processModel.getBtcWalletService();
String id = processModel.getOffer().getId();
Transaction preparedDepositTx = btcWalletService.getTxFromSerializedTx(processModel.getPreparedDepositTx());
Transaction preparedDelayedPayoutTx = checkNotNull(processModel.getPreparedDelayedPayoutTx());
byte[] buyerMultiSigPubKey = processModel.getMyMultiSigPubKey();
checkArgument(Arrays.equals(buyerMultiSigPubKey,
btcWalletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG).getPubKey()),
"buyerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
byte[] sellerMultiSigPubKey = trade.getTradingPeer().getMultiSigPubKey();
byte[] buyerSignature = processModel.getDelayedPayoutTxSignature();
byte[] sellerSignature = trade.getTradingPeer().getDelayedPayoutTxSignature();
Transaction signedDelayedPayoutTx = processModel.getTradeWalletService().finalizeUnconnectedDelayedPayoutTx(
preparedDelayedPayoutTx,
buyerMultiSigPubKey,
sellerMultiSigPubKey,
buyerSignature,
sellerSignature,
preparedDepositTx.getOutput(0).getValue());
trade.applyDelayedPayoutTxBytes(signedDelayedPayoutTx.bitcoinSerialize());
log.info("DelayedPayoutTxBytes = {}", Utilities.bytesAsHexString(trade.getDelayedPayoutTxBytes()));
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,65 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.core.util.Validator;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Transaction;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class BuyerProcessDelayedPayoutTxSignatureRequest extends TradeTask {
public BuyerProcessDelayedPayoutTxSignatureRequest(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
DelayedPayoutTxSignatureRequest request = (DelayedPayoutTxSignatureRequest) processModel.getTradeMessage();
checkNotNull(request);
Validator.checkTradeId(processModel.getOfferId(), request);
byte[] delayedPayoutTxAsBytes = checkNotNull(request.getDelayedPayoutTx());
Transaction preparedDelayedPayoutTx = processModel.getBtcWalletService().getTxFromSerializedTx(delayedPayoutTxAsBytes);
processModel.setPreparedDelayedPayoutTx(preparedDelayedPayoutTx);
trade.getTradingPeer().setDelayedPayoutTxSignature(checkNotNull(request.getDelayedPayoutTxSellerSignature()));
// When we receive that message the taker has published the taker fee, so we apply it to the trade.
// The takerFeeTx was sent in the first message. It should be part of DelayedPayoutTxSignatureRequest
// but that cannot be changed due backward compatibility issues. It is a left over from the old trade protocol.
trade.setTakerFeeTxId(processModel.getTakeOfferFeeTxId());
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,72 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BuyerProcessDepositTxAndDelayedPayoutTxMessage extends TradeTask {
public BuyerProcessDepositTxAndDelayedPayoutTxMessage(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
throw new RuntimeException("BuyerProcessDepositTxAndDelayedPayoutTxMessage invalid in xmr base pair");
// var message = checkNotNull((DepositTxAndDelayedPayoutTxMessage) processModel.getTradeMessage());
// checkNotNull(message);
// Validator.checkTradeId(processModel.getOfferId(), message);
//
// // To access tx confidence we need to add that tx into our wallet.
// byte[] depositTxBytes = checkNotNull(message.getDepositTx());
// Transaction depositTx = processModel.getBtcWalletService().getTxFromSerializedTx(depositTxBytes);
// // update with full tx
// Wallet wallet = processModel.getBtcWalletService().getWallet();
// Transaction committedDepositTx = WalletService.maybeAddSelfTxToWallet(depositTx, wallet);
// trade.applyDepositTx(committedDepositTx);
// BtcWalletService.printTx("depositTx received from peer", committedDepositTx);
//
// // To access tx confidence we need to add that tx into our wallet.
// byte[] delayedPayoutTxBytes = checkNotNull(message.getDelayedPayoutTx());
// trade.applyDelayedPayoutTxBytes(delayedPayoutTxBytes);
// BtcWalletService.printTx("delayedPayoutTx received from peer",
// checkNotNull(trade.getDelayedPayoutTx()));
//
// trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
//
// // If we got already the confirmation we don't want to apply an earlier state
// if (trade.getState().ordinal() < Trade.State.BUYER_SAW_DEPOSIT_TX_IN_NETWORK.ordinal()) {
// trade.setState(Trade.State.BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG);
// }
//
// processModel.getBtcWalletService().swapTradeEntryToAvailableEntry(trade.getId(),
// AddressEntry.Context.RESERVED_FOR_TRADE);
//
// complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,85 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.DelayedPayoutTxSignatureResponse;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.network.p2p.NodeAddress;
import bisq.network.p2p.SendDirectMessageListener;
import bisq.common.taskrunner.TaskRunner;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class BuyerSendsDelayedPayoutTxSignatureResponse extends TradeTask {
public BuyerSendsDelayedPayoutTxSignatureResponse(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
byte[] delayedPayoutTxSignature = checkNotNull(processModel.getDelayedPayoutTxSignature());
byte[] depositTxBytes = processModel.getDepositTx() != null
? processModel.getDepositTx().bitcoinSerialize() // set in BuyerAsTakerSignsDepositTx task
: processModel.getPreparedDepositTx(); // set in BuyerAsMakerCreatesAndSignsDepositTx task
DelayedPayoutTxSignatureResponse message = new DelayedPayoutTxSignatureResponse(UUID.randomUUID().toString(),
processModel.getOfferId(),
processModel.getMyNodeAddress(),
delayedPayoutTxSignature,
depositTxBytes);
NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress();
log.info("Send {} to peer {}. tradeId={}, uid={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
processModel.getP2PService().sendEncryptedDirectMessage(
peersNodeAddress,
trade.getTradingPeer().getPubKeyRing(),
message,
new SendDirectMessageListener() {
@Override
public void onArrived() {
log.info("{} arrived at peer {}. tradeId={}, uid={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
complete();
}
@Override
public void onFault(String errorMessage) {
log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
failed(errorMessage);
}
}
);
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,79 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.NetworkParameters;
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 BuyerSignsDelayedPayoutTx extends TradeTask {
public BuyerSignsDelayedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
Transaction preparedDelayedPayoutTx = checkNotNull(processModel.getPreparedDelayedPayoutTx());
BtcWalletService btcWalletService = processModel.getBtcWalletService();
NetworkParameters params = btcWalletService.getParams();
Transaction preparedDepositTx = new Transaction(params, processModel.getPreparedDepositTx());
String id = processModel.getOffer().getId();
byte[] buyerMultiSigPubKey = processModel.getMyMultiSigPubKey();
DeterministicKey myMultiSigKeyPair = btcWalletService.getMultiSigKeyPair(id, buyerMultiSigPubKey);
checkArgument(Arrays.equals(buyerMultiSigPubKey,
btcWalletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG).getPubKey()),
"buyerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
byte[] sellerMultiSigPubKey = trade.getTradingPeer().getMultiSigPubKey();
byte[] delayedPayoutTxSignature = processModel.getTradeWalletService().signDelayedPayoutTx(
preparedDelayedPayoutTx,
preparedDepositTx,
myMultiSigKeyPair,
buyerMultiSigPubKey,
sellerMultiSigPubKey);
processModel.setDelayedPayoutTxSignature(delayedPayoutTxSignature);
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,43 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BuyerVerifiesFinalDelayedPayoutTx extends TradeTask {
public BuyerVerifiesFinalDelayedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
throw new RuntimeException("BuyerVerifiesFinalDelayedPayoutTx not applicable for xmr");
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,71 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeDataValidation;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class BuyerVerifiesPreparedDelayedPayoutTx extends TradeTask {
public BuyerVerifiesPreparedDelayedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
var preparedDelayedPayoutTx = processModel.getPreparedDelayedPayoutTx();
TradeDataValidation.validateDelayedPayoutTx(trade,
preparedDelayedPayoutTx,
processModel.getBtcWalletService());
// If the deposit tx is non-malleable, we already know its final ID, so should check that now
// before sending any further data to the seller, to provide extra protection for the buyer.
if (isDepositTxNonMalleable()) {
var preparedDepositTx = processModel.getBtcWalletService().getTxFromSerializedTx(
processModel.getPreparedDepositTx());
TradeDataValidation.validatePayoutTxInput(preparedDepositTx, checkNotNull(preparedDelayedPayoutTx));
} else {
log.info("Deposit tx is malleable, so we skip preparedDelayedPayoutTx input validation.");
}
complete();
} catch (TradeDataValidation.ValidationException e) {
failed(e.getMessage());
} catch (Throwable t) {
failed(t);
}
}
private boolean isDepositTxNonMalleable() {
var buyerInputs = checkNotNull(processModel.getRawTransactionInputs());
var sellerInputs = checkNotNull(trade.getTradingPeer().getRawTransactionInputs());
return buyerInputs.stream().allMatch(processModel.getTradeWalletService()::isP2WH) &&
sellerInputs.stream().allMatch(processModel.getTradeWalletService()::isP2WH);
}
}

View File

@ -1,109 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer_as_maker;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.model.PreparedDepositTxAndMakerInputs;
import bisq.core.btc.model.RawTransactionInput;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.offer.Offer;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.TradingPeer;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.Coin;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class BuyerAsMakerCreatesAndSignsDepositTx extends TradeTask {
public BuyerAsMakerCreatesAndSignsDepositTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
Coin tradeAmount = checkNotNull(trade.getAmount(), "trade.getTradeAmount() must not be null");
BtcWalletService walletService = processModel.getBtcWalletService();
String id = processModel.getOffer().getId();
TradingPeer tradingPeer = trade.getTradingPeer();
Offer offer = checkNotNull(trade.getOffer());
Coin makerInputAmount = offer.getBuyerSecurityDeposit();
Optional<AddressEntry> addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG);
checkArgument(addressEntryOptional.isPresent(), "addressEntryOptional must be present");
AddressEntry makerMultiSigAddressEntry = addressEntryOptional.get();
processModel.getBtcWalletService().setCoinLockedInMultiSigAddressEntry(makerMultiSigAddressEntry, makerInputAmount.value);
walletService.saveAddressEntryList();
Coin msOutputAmount = makerInputAmount
.add(trade.getTxFee())
.add(offer.getSellerSecurityDeposit())
.add(tradeAmount);
List<RawTransactionInput> takerRawTransactionInputs = checkNotNull(tradingPeer.getRawTransactionInputs());
checkArgument(takerRawTransactionInputs.stream().allMatch(processModel.getTradeWalletService()::isP2WH),
"all takerRawTransactionInputs must be P2WH");
long takerChangeOutputValue = tradingPeer.getChangeOutputValue();
@Nullable String takerChangeAddressString = tradingPeer.getChangeOutputAddress();
Address makerAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
Address makerChangeAddress = walletService.getFreshAddressEntry().getAddress();
byte[] buyerPubKey = processModel.getMyMultiSigPubKey();
byte[] sellerPubKey = checkNotNull(tradingPeer.getMultiSigPubKey());
checkArgument(Arrays.equals(buyerPubKey,
makerMultiSigAddressEntry.getPubKey()),
"buyerPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
PreparedDepositTxAndMakerInputs result = processModel.getTradeWalletService().buyerAsMakerCreatesAndSignsDepositTx(
trade.getContractHash(),
makerInputAmount,
msOutputAmount,
takerRawTransactionInputs,
takerChangeOutputValue,
takerChangeAddressString,
makerAddress,
makerChangeAddress,
buyerPubKey,
sellerPubKey);
processModel.setPreparedDepositTx(result.depositTransaction);
processModel.setRawTransactionInputs(result.rawMakerInputs);
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,42 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer_as_maker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.maker.MakerSendsInputsForDepositTxResponse;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Transaction;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BuyerAsMakerSendsInputsForDepositTxResponse extends MakerSendsInputsForDepositTxResponse {
public BuyerAsMakerSendsInputsForDepositTxResponse(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected byte[] getPreparedDepositTx() {
Transaction preparedDepositTx = processModel.getBtcWalletService().getTxFromSerializedTx(processModel.getPreparedDepositTx());
// Remove witnesses from preparedDepositTx, so that the seller can still compute the final
// tx id, but cannot publish it before providing the buyer with a signed delayed payout tx.
return preparedDepositTx.bitcoinSerialize(false);
}
}

View File

@ -1,60 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer_as_taker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BuyerAsTakerCreatesDepositTxInputs extends TradeTask {
public BuyerAsTakerCreatesDepositTxInputs(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
throw new RuntimeException("Outputs not communicated in xmr integration");
// processModel.getTradeManager().requestPersistence();
// Coin txFee = trade.getTxFee();
// Coin takerInputAmount = checkNotNull(trade.getOffer()).getBuyerSecurityDeposit()
// .add(txFee)
// .add(txFee); // 2 times the fee as we need it for payout tx as well
// InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositTxInputs(
// processModel.getTakeOfferFeeTx(),
// takerInputAmount,
// txFee);
// processModel.setRawTransactionInputs(result.rawTransactionInputs);
// processModel.setChangeOutputValue(result.changeOutputValue);
// processModel.setChangeOutputAddress(result.changeOutputAddress);
//
// complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,77 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer_as_taker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BuyerAsTakerSendsDepositTxMessage extends TradeTask {
public BuyerAsTakerSendsDepositTxMessage(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
throw new RuntimeException("BuyerAsTakerSendsDepositTxMessage not implemented for xmr");
// if (processModel.getDepositTx() != null) {
// DepositTxMessage message = new DepositTxMessage(UUID.randomUUID().toString(),
// processModel.getOfferId(),
// processModel.getMyNodeAddress(),
// processModel.getDepositTx().bitcoinSerialize());
//
// NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress();
// log.info("Send {} to peer {}. tradeId={}, uid={}",
// message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
// processModel.getP2PService().sendEncryptedDirectMessage(
// peersNodeAddress,
// trade.getTradingPeer().getPubKeyRing(),
// message,
// new SendDirectMessageListener() {
// @Override
// public void onArrived() {
// log.info("{} arrived at peer {}. tradeId={}, uid={}",
// message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
// complete();
// }
//
// @Override
// public void onFault(String errorMessage) {
// log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
// message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
//
// appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
// failed();
// }
// }
// );
// } else {
// log.error("processModel.getDepositTx() = " + processModel.getDepositTx());
// failed("DepositTx is null");
// }
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,82 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.buyer_as_taker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BuyerAsTakerSignsDepositTx extends TradeTask {
public BuyerAsTakerSignsDepositTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
throw new RuntimeException("BuyerAsTakerSignsDepositTx not implemented for xmr");
/* log.debug("\n\n------------------------------------------------------------\n"
+ "Contract as json\n"
+ trade.getContractAsJson()
+ "\n------------------------------------------------------------\n");*/
// byte[] contractHash = Hash.getSha256Hash(checkNotNull(trade.getContractAsJson()));
// trade.setContractHash(contractHash);
// List<RawTransactionInput> buyerInputs = checkNotNull(processModel.getRawTransactionInputs(), "buyerInputs must not be null");
// BtcWalletService walletService = processModel.getBtcWalletService();
// String id = processModel.getOffer().getId();
//
// Optional<AddressEntry> addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG);
// 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().multiply(2)));
// walletService.saveAddressEntryList();
//
// TradingPeer tradingPeer = trade.getTradingPeer();
// byte[] buyerMultiSigPubKey = processModel.getMyMultiSigPubKey();
// checkArgument(Arrays.equals(buyerMultiSigPubKey, buyerMultiSigAddressEntry.getPubKey()),
// "buyerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
//
// List<RawTransactionInput> sellerInputs = checkNotNull(tradingPeer.getRawTransactionInputs());
// byte[] sellerMultiSigPubKey = tradingPeer.getMultiSigPubKey();
// Transaction depositTx = processModel.getTradeWalletService().takerSignsDepositTx(
// false,
// contractHash,
// processModel.getPreparedDepositTx(),
// buyerInputs,
// sellerInputs,
// buyerMultiSigPubKey,
// sellerMultiSigPubKey);
// processModel.setDepositTx(depositTx);
//
// complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,125 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.maker;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.InputsForDepositTxResponse;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.network.p2p.NodeAddress;
import bisq.network.p2p.SendDirectMessageListener;
import bisq.common.crypto.Sig;
import bisq.common.taskrunner.TaskRunner;
import java.security.PrivateKey;
import java.util.Arrays;
import java.util.Date;
import java.util.Optional;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public abstract class MakerSendsInputsForDepositTxResponse extends TradeTask {
public MakerSendsInputsForDepositTxResponse(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
protected abstract byte[] getPreparedDepositTx();
@Override
protected void run() {
try {
runInterceptHook();
BtcWalletService walletService = processModel.getBtcWalletService();
String id = processModel.getOffer().getId();
Optional<AddressEntry> optionalMultiSigAddressEntry = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG);
checkArgument(optionalMultiSigAddressEntry.isPresent(), "addressEntry must be set here.");
AddressEntry makerPayoutAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.TRADE_PAYOUT);
byte[] makerMultiSigPubKey = processModel.getMyMultiSigPubKey();
checkArgument(Arrays.equals(makerMultiSigPubKey,
optionalMultiSigAddressEntry.get().getPubKey()),
"makerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
byte[] preparedDepositTx = getPreparedDepositTx();
// Maker has to use preparedDepositTx as nonce.
// He cannot manipulate the preparedDepositTx - so we avoid to have a challenge protocol for passing the
// nonce we want to get signed.
// This is used for verifying the peers account age witness
PrivateKey privateKey = processModel.getKeyRing().getSignatureKeyPair().getPrivate();
byte[] signatureOfNonce = Sig.sign(privateKey, preparedDepositTx);
InputsForDepositTxResponse message = new InputsForDepositTxResponse(
processModel.getOfferId(),
checkNotNull(processModel.getPaymentAccountPayload(trade)),
processModel.getAccountId(),
makerMultiSigPubKey,
trade.getContractAsJson(),
trade.getMaker().getContractSignature(),
makerPayoutAddressEntry.getAddressString(),
preparedDepositTx,
processModel.getRawTransactionInputs(),
processModel.getMyNodeAddress(),
UUID.randomUUID().toString(),
signatureOfNonce,
new Date().getTime(),
trade.getLockTime());
trade.setState(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST);
processModel.getTradeManager().requestPersistence();
NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress();
log.info("Send {} to peer {}. tradeId={}, uid={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
processModel.getP2PService().sendEncryptedDirectMessage(
peersNodeAddress,
trade.getTradingPeer().getPubKeyRing(),
message,
new SendDirectMessageListener() {
@Override
public void onArrived() {
log.info("{} arrived at peer {}. tradeId={}, uid={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
trade.setState(Trade.State.MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST);
processModel.getTradeManager().requestPersistence();
complete();
}
@Override
public void onFault(String errorMessage) {
log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
trade.setState(Trade.State.MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST);
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
processModel.getTradeManager().requestPersistence();
failed(errorMessage);
}
}
);
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,49 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.maker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MakerVerifyTakerFeePayment extends TradeTask {
public MakerVerifyTakerFeePayment(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
//TODO missing impl.
// int numOfPeersSeenTx = processModel.getWalletService().getNumOfPeersSeenTx(processModel.getTakeOfferFeeTxId());
/* if (numOfPeersSeenTx > 2) {
resultHandler.handleResult();
}*/
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,50 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.mediation;
import bisq.core.support.dispute.mediation.MediationResultState;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.BroadcastPayoutTx;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BroadcastMediatedPayoutTx extends BroadcastPayoutTx {
public BroadcastMediatedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
super.run();
} catch (Throwable t) {
failed(t);
}
}
@Override
protected void setState() {
trade.setMediationResultState(MediationResultState.PAYOUT_TX_PUBLISHED);
processModel.getTradeManager().requestPersistence();
}
}

View File

@ -1,49 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.BroadcastPayoutTx;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SellerBroadcastPayoutTx extends BroadcastPayoutTx {
public SellerBroadcastPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
super.run();
} catch (Throwable t) {
failed(t);
}
}
@Override
protected void setState() {
trade.setState(Trade.State.SELLER_PUBLISHED_PAYOUT_TX);
processModel.getTradeManager().requestPersistence();
}
}

View File

@ -1,50 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
import bisq.core.btc.wallet.TradeWalletService;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeDataValidation;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class SellerCreatesDelayedPayoutTx extends TradeTask {
public SellerCreatesDelayedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
throw new RuntimeException("SellerCreatesDelayedPayoutTx not implemented for xmr");
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,78 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import bisq.common.util.Utilities;
import org.bitcoinj.core.Transaction;
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 SellerFinalizesDelayedPayoutTx extends TradeTask {
public SellerFinalizesDelayedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
Transaction preparedDelayedPayoutTx = checkNotNull(processModel.getPreparedDelayedPayoutTx());
BtcWalletService btcWalletService = processModel.getBtcWalletService();
String id = processModel.getOffer().getId();
byte[] buyerMultiSigPubKey = trade.getTradingPeer().getMultiSigPubKey();
byte[] sellerMultiSigPubKey = processModel.getMyMultiSigPubKey();
checkArgument(Arrays.equals(sellerMultiSigPubKey,
btcWalletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG).getPubKey()),
"sellerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
byte[] buyerSignature = trade.getTradingPeer().getDelayedPayoutTxSignature();
byte[] sellerSignature = processModel.getDelayedPayoutTxSignature();
Transaction signedDelayedPayoutTx = processModel.getTradeWalletService().finalizeDelayedPayoutTx(
preparedDelayedPayoutTx,
buyerMultiSigPubKey,
sellerMultiSigPubKey,
buyerSignature,
sellerSignature);
trade.applyDelayedPayoutTx(signedDelayedPayoutTx);
log.info("DelayedPayoutTxBytes = {}", Utilities.bytesAsHexString(trade.getDelayedPayoutTxBytes()));
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,62 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.DelayedPayoutTxSignatureResponse;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
import static bisq.core.util.Validator.checkTradeId;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class SellerProcessDelayedPayoutTxSignatureResponse extends TradeTask {
public SellerProcessDelayedPayoutTxSignatureResponse(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
DelayedPayoutTxSignatureResponse response = (DelayedPayoutTxSignatureResponse) processModel.getTradeMessage();
checkNotNull(response);
checkTradeId(processModel.getOfferId(), response);
trade.getTradingPeer().setDelayedPayoutTxSignature(checkNotNull(response.getDelayedPayoutTxBuyerSignature()));
processModel.getTradeWalletService().sellerAddsBuyerWitnessesToDepositTx(
processModel.getDepositTx(),
processModel.getBtcWalletService().getTxFromSerializedTx(response.getDepositTx())
);
// update to the latest peer address of our peer if the message is correct
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,86 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.network.p2p.NodeAddress;
import bisq.network.p2p.SendDirectMessageListener;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Transaction;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class SellerSendDelayedPayoutTxSignatureRequest extends TradeTask {
public SellerSendDelayedPayoutTxSignatureRequest(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
Transaction preparedDelayedPayoutTx = checkNotNull(processModel.getPreparedDelayedPayoutTx(),
"processModel.getPreparedDelayedPayoutTx() must not be null");
byte[] delayedPayoutTxSignature = checkNotNull(processModel.getDelayedPayoutTxSignature(),
"processModel.getDelayedPayoutTxSignature() must not be null");
DelayedPayoutTxSignatureRequest message = new DelayedPayoutTxSignatureRequest(UUID.randomUUID().toString(),
processModel.getOfferId(),
processModel.getMyNodeAddress(),
preparedDelayedPayoutTx.bitcoinSerialize(),
delayedPayoutTxSignature);
NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress();
log.info("Send {} to peer {}. tradeId={}, uid={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
processModel.getP2PService().sendEncryptedDirectMessage(
peersNodeAddress,
trade.getTradingPeer().getPubKeyRing(),
message,
new SendDirectMessageListener() {
@Override
public void onArrived() {
log.info("{} arrived at peer {}. tradeId={}, uid={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
complete();
}
@Override
public void onFault(String errorMessage) {
log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
failed();
}
}
);
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,80 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.NetworkParameters;
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 SellerSignsDelayedPayoutTx extends TradeTask {
public SellerSignsDelayedPayoutTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
Transaction preparedDelayedPayoutTx = checkNotNull(processModel.getPreparedDelayedPayoutTx());
BtcWalletService btcWalletService = processModel.getBtcWalletService();
NetworkParameters params = btcWalletService.getParams();
Transaction preparedDepositTx = new Transaction(params, processModel.getPreparedDepositTx());
String id = processModel.getOffer().getId();
byte[] sellerMultiSigPubKey = processModel.getMyMultiSigPubKey();
DeterministicKey myMultiSigKeyPair = btcWalletService.getMultiSigKeyPair(id, sellerMultiSigPubKey);
checkArgument(Arrays.equals(sellerMultiSigPubKey,
btcWalletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG).getPubKey()),
"sellerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
byte[] buyerMultiSigPubKey = trade.getTradingPeer().getMultiSigPubKey();
byte[] delayedPayoutTxSignature = processModel.getTradeWalletService().signDelayedPayoutTx(
preparedDelayedPayoutTx,
preparedDepositTx,
myMultiSigKeyPair,
buyerMultiSigPubKey,
sellerMultiSigPubKey);
processModel.setDelayedPayoutTxSignature(delayedPayoutTxSignature);
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,116 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller_as_maker;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.model.PreparedDepositTxAndMakerInputs;
import bisq.core.btc.model.RawTransactionInput;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.offer.Offer;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.TradingPeer;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.crypto.Hash;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.Coin;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class SellerAsMakerCreatesUnsignedDepositTx extends TradeTask {
public SellerAsMakerCreatesUnsignedDepositTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
checkNotNull(trade.getAmount(), "trade.getTradeAmount() must not be null");
BtcWalletService walletService = processModel.getBtcWalletService();
String id = processModel.getOffer().getId();
TradingPeer tradingPeer = trade.getTradingPeer();
Offer offer = checkNotNull(trade.getOffer());
// params
byte[] contractHash = Hash.getSha256Hash(checkNotNull(trade.getContractAsJson()));
trade.setContractHash(contractHash);
log.debug("\n\n------------------------------------------------------------\n"
+ "Contract as json\n"
+ trade.getContractAsJson()
+ "\n------------------------------------------------------------\n");
Coin makerInputAmount = offer.getSellerSecurityDeposit().add(trade.getAmount());
Optional<AddressEntry> addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG);
checkArgument(addressEntryOptional.isPresent(), "addressEntryOptional must be present");
AddressEntry makerMultiSigAddressEntry = addressEntryOptional.get();
processModel.getBtcWalletService().setCoinLockedInMultiSigAddressEntry(makerMultiSigAddressEntry, makerInputAmount.value);
walletService.saveAddressEntryList();
Coin msOutputAmount = makerInputAmount
.add(trade.getTxFee())
.add(offer.getBuyerSecurityDeposit());
List<RawTransactionInput> takerRawTransactionInputs = checkNotNull(tradingPeer.getRawTransactionInputs());
checkArgument(takerRawTransactionInputs.stream().allMatch(processModel.getTradeWalletService()::isP2WH),
"all takerRawTransactionInputs must be P2WH");
long takerChangeOutputValue = tradingPeer.getChangeOutputValue();
String takerChangeAddressString = tradingPeer.getChangeOutputAddress();
Address makerAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
Address makerChangeAddress = walletService.getFreshAddressEntry().getAddress();
byte[] buyerPubKey = tradingPeer.getMultiSigPubKey();
byte[] sellerPubKey = processModel.getMyMultiSigPubKey();
checkArgument(Arrays.equals(sellerPubKey,
makerMultiSigAddressEntry.getPubKey()),
"sellerPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
PreparedDepositTxAndMakerInputs result = processModel.getTradeWalletService().sellerAsMakerCreatesDepositTx(
contractHash,
makerInputAmount,
msOutputAmount,
takerRawTransactionInputs,
takerChangeOutputValue,
takerChangeAddressString,
makerAddress,
makerChangeAddress,
buyerPubKey,
sellerPubKey);
processModel.setPreparedDepositTx(result.depositTransaction);
processModel.setRawTransactionInputs(result.rawMakerInputs);
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,59 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller_as_maker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Transaction;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class SellerAsMakerFinalizesDepositTx extends TradeTask {
public SellerAsMakerFinalizesDepositTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
if (true) throw new RuntimeException("SellerAsMakerFinalizesDepositTx not implemented for xmr");
byte[] takersRawPreparedDepositTx = checkNotNull(trade.getTradingPeer().getPreparedDepositTx());
byte[] myRawPreparedDepositTx = checkNotNull(processModel.getPreparedDepositTx());
Transaction takersDepositTx = processModel.getBtcWalletService().getTxFromSerializedTx(takersRawPreparedDepositTx);
Transaction myDepositTx = processModel.getBtcWalletService().getTxFromSerializedTx(myRawPreparedDepositTx);
int numTakersInputs = checkNotNull(trade.getTradingPeer().getRawTransactionInputs()).size();
processModel.getTradeWalletService().sellerAsMakerFinalizesDepositTx(myDepositTx, takersDepositTx, numTakersInputs);
processModel.setDepositTx(myDepositTx);
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,58 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller_as_maker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SellerAsMakerProcessDepositTxMessage extends TradeTask {
public SellerAsMakerProcessDepositTxMessage(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
throw new RuntimeException("SellerAsMakerProcessDepositTxMessage needs updated for XMR");
// try {
// runInterceptHook();
// log.debug("current trade state " + trade.getState());
// DepositTxMessage message = (DepositTxMessage) processModel.getTradeMessage();
// Validator.checkTradeId(processModel.getOfferId(), message);
// checkNotNull(message);
//
// trade.getTradingPeer().setPreparedDepositTx(checkNotNull(message.getDepositTxWithoutWitnesses()));
// trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
//
// // When we receive that message the taker has published the taker fee, so we apply it to the trade.
// // The takerFeeTx was sent in the first message. It should be part of DelayedPayoutTxSignatureRequest
// // but that cannot be changed due backward compatibility issues. It is a left over from the old trade protocol.
// trade.setTakerFeeTxId(processModel.getTakeOfferFeeTxId());
//
// processModel.getTradeManager().requestPersistence();
//
// complete();
// } catch (Throwable t) {
// failed(t);
// }
}
}

View File

@ -1,50 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller_as_maker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.maker.MakerSendsInputsForDepositTxResponse;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.script.Script;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SellerAsMakerSendsInputsForDepositTxResponse extends MakerSendsInputsForDepositTxResponse {
public SellerAsMakerSendsInputsForDepositTxResponse(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected byte[] getPreparedDepositTx() {
Transaction preparedDepositTx = processModel.getBtcWalletService().getTxFromSerializedTx(processModel.getPreparedDepositTx());
preparedDepositTx.getInputs().forEach(input -> {
// Remove signature before sending to peer as we don't want to risk that buyer could publish deposit tx
// before we have received his signature for the delayed payout tx.
input.setScriptSig(new Script(new byte[]{}));
});
processModel.getTradeManager().requestPersistence();
// Make sure witnesses are removed as well before sending, to cover the segwit case.
return preparedDepositTx.bitcoinSerialize(false);
}
}

View File

@ -1,62 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller_as_taker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SellerAsTakerCreatesDepositTxInputs extends TradeTask {
public SellerAsTakerCreatesDepositTxInputs(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
throw new RuntimeException("XMR integration does not communicate outputs");
// Coin tradeAmount = checkNotNull(trade.getTradeAmount());
// Offer offer = checkNotNull(trade.getOffer());
// Coin txFee = trade.getTxFee();
// Coin takerInputAmount = offer.getSellerSecurityDeposit()
// .add(txFee)
// .add(txFee) // We add 2 times the fee as one is for the payout tx
// .add(tradeAmount);
// InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositTxInputs(
// processModel.getTakeOfferFeeTx(),
// takerInputAmount,
// txFee);
//
// processModel.setRawTransactionInputs(result.rawTransactionInputs);
// processModel.setChangeOutputValue(result.changeOutputValue);
// processModel.setChangeOutputAddress(result.changeOutputAddress);
//
// processModel.getTradeManager().requestPersistence();
//
// complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,104 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.seller_as_taker;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.model.RawTransactionInput;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.offer.Offer;
import bisq.core.trade.Contract;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.TradingPeer;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class SellerAsTakerSignsDepositTx extends TradeTask {
public SellerAsTakerSignsDepositTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
if (true) throw new RuntimeException("SellerAsTakerSignsDepositTx not implemented for xmr");
List<RawTransactionInput> sellerInputs = checkNotNull(processModel.getRawTransactionInputs(),
"sellerInputs must not be null");
BtcWalletService walletService = processModel.getBtcWalletService();
String id = processModel.getOffer().getId();
Optional<AddressEntry> optionalMultiSigAddressEntry = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG);
checkArgument(optionalMultiSigAddressEntry.isPresent(), "addressEntryOptional must be present");
AddressEntry sellerMultiSigAddressEntry = optionalMultiSigAddressEntry.get();
byte[] sellerMultiSigPubKey = processModel.getMyMultiSigPubKey();
checkArgument(Arrays.equals(sellerMultiSigPubKey,
sellerMultiSigAddressEntry.getPubKey()),
"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());
Coin totalFee = trade.getTxFee().multiply(2); // Fee for deposit and payout tx
Coin multiSigValue = sellerInput.subtract(totalFee);
processModel.getBtcWalletService().setCoinLockedInMultiSigAddressEntry(sellerMultiSigAddressEntry, multiSigValue.value);
walletService.saveAddressEntryList();
Offer offer = trade.getOffer();
Coin msOutputAmount = offer.getBuyerSecurityDeposit().add(offer.getSellerSecurityDeposit()).add(trade.getTxFee())
.add(checkNotNull(trade.getAmount()));
TradingPeer tradingPeer = trade.getTradingPeer();
Transaction depositTx = processModel.getTradeWalletService().takerSignsDepositTx(
true,
trade.getContractHash(),
processModel.getPreparedDepositTx(),
msOutputAmount,
checkNotNull(tradingPeer.getRawTransactionInputs()),
sellerInputs,
tradingPeer.getMultiSigPubKey(),
sellerMultiSigPubKey);
// We set the deposit tx to trade once we have it published
processModel.setDepositTx(depositTx);
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
Contract contract = trade.getContract();
if (contract != null)
contract.printDiff(trade.getTradingPeer().getContractAsJson());
failed(t);
}
}
}

View File

@ -1,93 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.taker;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.InputsForDepositTxResponse;
import bisq.core.trade.protocol.TradingPeer;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.config.Config;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
import static bisq.core.util.Validator.checkTradeId;
import static bisq.core.util.Validator.nonEmptyStringOf;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class TakerProcessesInputsForDepositTxResponse extends TradeTask {
public TakerProcessesInputsForDepositTxResponse(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
InputsForDepositTxResponse response = (InputsForDepositTxResponse) processModel.getTradeMessage();
checkTradeId(processModel.getOfferId(), response);
checkNotNull(response);
TradingPeer tradingPeer = trade.getTradingPeer();
tradingPeer.setPaymentAccountPayload(checkNotNull(response.getMakerPaymentAccountPayload()));
tradingPeer.setAccountId(nonEmptyStringOf(response.getMakerAccountId()));
tradingPeer.setMultiSigPubKey(checkNotNull(response.getMakerMultiSigPubKey()));
tradingPeer.setContractAsJson(nonEmptyStringOf(response.getMakerContractAsJson()));
tradingPeer.setContractSignature(nonEmptyStringOf(response.getMakerContractSignature()));
tradingPeer.setPayoutAddressString(nonEmptyStringOf(response.getMakerPayoutAddressString()));
tradingPeer.setRawTransactionInputs(checkNotNull(response.getMakerInputs()));
byte[] preparedDepositTx = checkNotNull(response.getPreparedDepositTx());
processModel.setPreparedDepositTx(preparedDepositTx);
long lockTime = response.getLockTime();
if (Config.baseCurrencyNetwork().isMainnet()) {
int myLockTime = processModel.getBtcWalletService().getBestChainHeight() +
Restrictions.getLockTime(processModel.getOffer().getPaymentMethod().isBlockchain());
// We allow a tolerance of 3 blocks as BestChainHeight might be a bit different on maker and taker in case a new
// block was just found
checkArgument(Math.abs(lockTime - myLockTime) <= 3,
"Lock time of maker is more than 3 blocks different to the lockTime I " +
"calculated. Makers lockTime= " + lockTime + ", myLockTime=" + myLockTime);
}
trade.setLockTime(lockTime);
long delay = processModel.getBtcWalletService().getBestChainHeight() - lockTime;
log.info("lockTime={}, delay={}", lockTime, delay);
// Maker has to sign preparedDepositTx. He cannot manipulate the preparedDepositTx - so we avoid to have a
// challenge protocol for passing the nonce we want to get signed.
tradingPeer.setAccountAgeWitnessNonce(preparedDepositTx);
tradingPeer.setAccountAgeWitnessSignature(checkNotNull(response.getAccountAgeWitnessSignatureOfPreparedDepositTx()));
tradingPeer.setCurrentDate(response.getCurrentDate());
checkArgument(response.getMakerInputs().size() > 0);
// update to the latest peer address of our peer if the message is correct
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
processModel.getTradeManager().requestPersistence();
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View File

@ -1,58 +0,0 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.trade.protocol.tasks.taker;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import lombok.extern.slf4j.Slf4j;
import monero.wallet.model.MoneroTxWallet;
@Slf4j
public class TakerPublishFeeTx extends TradeTask {
public TakerPublishFeeTx(TaskRunner<Trade> taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
// We committed to be sure the tx gets into the wallet even in the broadcast process it would be
// committed as well, but if user would close app before success handler returns the commit would not
// be done.
MoneroTxWallet takeOfferFeeTx = processModel.getTakeOfferFeeTx();
processModel.getProvider().getXmrWalletService().getWallet().relayTx(takeOfferFeeTx);
System.out.println("TAKER PUBLISHED FEE TX");
System.out.println(takeOfferFeeTx);
trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX);
complete();
} catch (Throwable t) {
log.error(t.toString());
t.printStackTrace();
trade.setErrorMessage("An error occurred.\n Error message:\n" + t.getMessage());
failed(t);
}
}
}

View File

@ -26,45 +26,20 @@ import bisq.core.offer.availability.tasks.SendOfferAvailabilityRequest;
import bisq.core.offer.placeoffer.tasks.AddToOfferBook;
import bisq.core.offer.placeoffer.tasks.MakerReservesOfferFunds;
import bisq.core.offer.placeoffer.tasks.ValidateOffer;
import bisq.core.trade.protocol.TakerVerifyMakerFeePayment;
import bisq.core.trade.protocol.tasks.ApplyFilter;
import bisq.core.trade.protocol.tasks.BuyerPreparesPaymentSentMessage;
import bisq.core.trade.protocol.tasks.BuyerProcessesPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.BuyerSendsPaymentSentMessage;
import bisq.core.trade.protocol.tasks.BuyerSetupPayoutTxListener;
import bisq.core.trade.protocol.tasks.MakerSetsLockTime;
import bisq.core.trade.protocol.tasks.MaybeRemoveOpenOffer;
import bisq.core.trade.protocol.tasks.SellerPreparesPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.SellerProcessesPaymentSentMessage;
import bisq.core.trade.protocol.tasks.SellerPublishesDepositTx;
import bisq.core.trade.protocol.tasks.SellerPublishesTradeStatistics;
import bisq.core.trade.protocol.tasks.SellerSendsPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
import bisq.core.trade.protocol.tasks.buyer.BuyerPreparesPaymentSentMessage;
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDepositTxAndDelayedPayoutTxMessage;
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessesPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.buyer.BuyerSendsPaymentSentMessage;
import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse;
import bisq.core.trade.protocol.tasks.buyer.BuyerSetupPayoutTxListener;
import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesFinalDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerCreatesAndSignsDepositTx;
import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerSendsInputsForDepositTxResponse;
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerCreatesDepositTxInputs;
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSendsDepositTxMessage;
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx;
import bisq.core.trade.protocol.tasks.maker.MaybeRemoveOpenOffer;
import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime;
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.seller.SellerFinalizesDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.seller.SellerProcessesPaymentSentMessage;
import bisq.core.trade.protocol.tasks.seller.SellerProcessDelayedPayoutTxSignatureResponse;
import bisq.core.trade.protocol.tasks.seller.SellerPublishesDepositTx;
import bisq.core.trade.protocol.tasks.seller.SellerPublishesTradeStatistics;
import bisq.core.trade.protocol.tasks.seller.SellerSendDelayedPayoutTxSignatureRequest;
import bisq.core.trade.protocol.tasks.seller.SellerSendsPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.seller.SellerPreparesPaymentReceivedMessage;
import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx;
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerCreatesUnsignedDepositTx;
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerFinalizesDepositTx;
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerSendsInputsForDepositTxResponse;
import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerCreatesDepositTxInputs;
import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerSignsDepositTx;
import bisq.core.trade.protocol.tasks.taker.TakerProcessesInputsForDepositTxResponse;
import bisq.core.trade.protocol.tasks.taker.TakerPublishFeeTx;
import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment;
import bisq.common.taskrunner.Task;
import bisq.common.util.Tuple2;
@ -118,19 +93,10 @@ public class DebugView extends InitializableView<GridPane, Void> {
FXCollections.observableArrayList(Arrays.asList(
ApplyFilter.class,
TakerVerifyMakerFeePayment.class,
SellerAsTakerCreatesDepositTxInputs.class,
TakerProcessesInputsForDepositTxResponse.class,
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
TakerPublishFeeTx.class,
SellerAsTakerSignsDepositTx.class,
SellerCreatesDelayedPayoutTx.class,
SellerSendDelayedPayoutTxSignatureRequest.class,
SellerProcessDelayedPayoutTxSignatureResponse.class,
SellerSignsDelayedPayoutTx.class,
SellerFinalizesDelayedPayoutTx.class,
//SellerSendsDepositTxAndDelayedPayoutTxMessage.class,
SellerPublishesDepositTx.class,
SellerPublishesTradeStatistics.class,
@ -151,22 +117,11 @@ public class DebugView extends InitializableView<GridPane, Void> {
FXCollections.observableArrayList(Arrays.asList(
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
MakerVerifyTakerFeePayment.class,
MakerSetsLockTime.class,
BuyerAsMakerCreatesAndSignsDepositTx.class,
BuyerAsMakerSendsInputsForDepositTxResponse.class,
BuyerProcessDelayedPayoutTxSignatureRequest.class,
MaybeRemoveOpenOffer.class,
BuyerVerifiesPreparedDelayedPayoutTx.class,
BuyerSignsDelayedPayoutTx.class,
BuyerSendsDelayedPayoutTxSignatureResponse.class,
BuyerProcessDepositTxAndDelayedPayoutTxMessage.class,
BuyerVerifiesFinalDelayedPayoutTx.class,
ApplyFilter.class,
MakerVerifyTakerFeePayment.class,
BuyerPreparesPaymentSentMessage.class,
BuyerSetupPayoutTxListener.class,
BuyerSendsPaymentSentMessage.class,
@ -180,22 +135,9 @@ public class DebugView extends InitializableView<GridPane, Void> {
FXCollections.observableArrayList(Arrays.asList(
ApplyFilter.class,
TakerVerifyMakerFeePayment.class,
BuyerAsTakerCreatesDepositTxInputs.class,
TakerProcessesInputsForDepositTxResponse.class,
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
TakerPublishFeeTx.class,
BuyerAsTakerSignsDepositTx.class,
BuyerAsTakerSendsDepositTxMessage.class,
BuyerProcessDelayedPayoutTxSignatureRequest.class,
BuyerVerifiesPreparedDelayedPayoutTx.class,
BuyerSignsDelayedPayoutTx.class,
BuyerSendsDelayedPayoutTxSignatureResponse.class,
BuyerProcessDepositTxAndDelayedPayoutTxMessage.class,
BuyerVerifiesFinalDelayedPayoutTx.class,
ApplyFilter.class,
TakerVerifyMakerFeePayment.class,
@ -209,30 +151,19 @@ public class DebugView extends InitializableView<GridPane, Void> {
FXCollections.observableArrayList(Arrays.asList(
ApplyFilter.class,
VerifyPeersAccountAgeWitness.class,
MakerVerifyTakerFeePayment.class,
MakerSetsLockTime.class,
SellerAsMakerCreatesUnsignedDepositTx.class,
SellerAsMakerSendsInputsForDepositTxResponse.class,
//SellerAsMakerProcessDepositTxMessage.class,
MaybeRemoveOpenOffer.class,
SellerAsMakerFinalizesDepositTx.class,
SellerCreatesDelayedPayoutTx.class,
SellerSendDelayedPayoutTxSignatureRequest.class,
SellerProcessDelayedPayoutTxSignatureResponse.class,
SellerSignsDelayedPayoutTx.class,
SellerFinalizesDelayedPayoutTx.class,
//SellerSendsDepositTxAndDelayedPayoutTxMessage.class,
SellerPublishesDepositTx.class,
SellerPublishesTradeStatistics.class,
SellerProcessesPaymentSentMessage.class,
ApplyFilter.class,
MakerVerifyTakerFeePayment.class,
ApplyFilter.class,
MakerVerifyTakerFeePayment.class,
SellerPreparesPaymentReceivedMessage.class,
//SellerBroadcastPayoutTx.class, // TODO (woodser): removed from main pipeline; debug view?
SellerSendsPaymentReceivedMessage.class

View File

@ -400,7 +400,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
trade != null ? trade.getShortId() : "trade is null");
switch (tradeState) {
// #################### Phase PREPARATION
// preparation
case PREPARATION:
case CONTRACT_SIGNATURE_REQUESTED:
case CONTRACT_SIGNED:
@ -408,50 +408,23 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
buyerState.set(BuyerState.UNDEFINED);
break;
// At first part maker/taker have different roles
// taker perspective
// #################### Phase TAKER_FEE_PAID
case TAKER_PUBLISHED_TAKER_FEE_TX:
// deposit requested
case SENT_PUBLISH_DEPOSIT_TX_REQUEST:
case SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST:
case STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST:
case SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST:
// PUBLISH_DEPOSIT_TX_REQUEST
// maker perspective
case MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST:
case MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST:
case MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST:
case MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST:
// taker perspective
case TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST:
// We don't have a UI state for that, we still have not a ready initiated trade
sellerState.set(UNDEFINED);
buyerState.set(BuyerState.UNDEFINED);
break;
// #################### Phase DEPOSIT_PAID
case ARBITRATOR_PUBLISHED_DEPOSIT_TX:
case TAKER_SAW_DEPOSIT_TX_IN_NETWORK:
// DEPOSIT_TX_PUBLISHED_MSG
// taker perspective
case TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG:
case TAKER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG:
case TAKER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG:
case TAKER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG:
// maker perspective
case MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG:
// Alternatively the maker could have seen the deposit tx earlier before he received the DEPOSIT_TX_PUBLISHED_MSG
case MAKER_SAW_DEPOSIT_TX_IN_NETWORK:
// deposit published
case ARBITRATOR_PUBLISHED_DEPOSIT_TXS:
case SAW_DEPOSIT_TXS_IN_NETWORK:
buyerState.set(BuyerState.STEP1);
sellerState.set(SellerState.STEP1);
break;
// buyer and seller step 2
// #################### Phase DEPOSIT_UNLOCKED
case DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN:
// deposit unlocked
case DEPOSIT_TXS_UNLOCKED_IN_BLOCKCHAIN:
sellerState.set(SellerState.STEP2);
buyerState.set(BuyerState.STEP2);
break;

View File

@ -610,7 +610,7 @@ public class BuyerStep2View extends TradeStepView {
//TODO seems this was a hack to enable repeated confirm???
if (trade.isPaymentSent()) {
trade.setState(Trade.State.DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN);
trade.setState(Trade.State.DEPOSIT_TXS_UNLOCKED_IN_BLOCKCHAIN);
model.dataModel.getTradeManager().requestPersistence();
}

View File

@ -1629,41 +1629,33 @@ message Trade {
MULTISIG_COMPLETED = 4;
CONTRACT_SIGNATURE_REQUESTED = 5;
CONTRACT_SIGNED = 6;
TAKER_PUBLISHED_TAKER_FEE_TX = 7;
MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST = 8;
MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST = 9;
MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST = 10;
MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST = 11;
TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST = 12;
ARBITRATOR_PUBLISHED_DEPOSIT_TX = 13;
TAKER_SAW_DEPOSIT_TX_IN_NETWORK = 14;
TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG = 15;
TAKER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG = 16;
TAKER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG = 17;
TAKER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG = 18;
MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG = 19;
MAKER_SAW_DEPOSIT_TX_IN_NETWORK = 20;
DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN = 21;
BUYER_CONFIRMED_IN_UI_PAYMENT_SENT = 22;
BUYER_SENT_PAYMENT_SENT_MSG = 23;
BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG = 24;
BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG = 25;
BUYER_SEND_FAILED_PAYMENT_SENT_MSG = 26;
SELLER_RECEIVED_PAYMENT_SENT_MSG = 27;
SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT = 28;
SELLER_SENT_PAYMENT_RECEIVED_MSG = 29;
SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG = 30;
SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG = 31;
SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG = 32;
SELLER_PUBLISHED_PAYOUT_TX = 33;
SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG = 34;
SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG = 35;
SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG = 36;
SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG = 37;
BUYER_RECEIVED_PAYOUT_TX_PUBLISHED_MSG = 38;
BUYER_SAW_PAYOUT_TX_IN_NETWORK = 39;
BUYER_PUBLISHED_PAYOUT_TX = 40;
WITHDRAW_COMPLETED = 41;
SENT_PUBLISH_DEPOSIT_TX_REQUEST = 7;
SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST = 8;
STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST = 9;
SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST = 10;
ARBITRATOR_PUBLISHED_DEPOSIT_TXS = 11;
SAW_DEPOSIT_TXS_IN_NETWORK = 12;
DEPOSIT_TXS_UNLOCKED_IN_BLOCKCHAIN = 13;
BUYER_CONFIRMED_IN_UI_PAYMENT_SENT = 14;
BUYER_SENT_PAYMENT_SENT_MSG = 15;
BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG = 16;
BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG = 17;
BUYER_SEND_FAILED_PAYMENT_SENT_MSG = 18;
SELLER_RECEIVED_PAYMENT_SENT_MSG = 19;
SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT = 20;
SELLER_SENT_PAYMENT_RECEIVED_MSG = 21;
SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG = 22;
SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG = 23;
SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG = 24;
SELLER_PUBLISHED_PAYOUT_TX = 25;
SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG = 26;
SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG = 27;
SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG = 28;
SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG = 29;
BUYER_RECEIVED_PAYOUT_TX_PUBLISHED_MSG = 30;
BUYER_SAW_PAYOUT_TX_IN_NETWORK = 31;
BUYER_PUBLISHED_PAYOUT_TX = 32;
WITHDRAW_COMPLETED = 33;
}
enum Phase {