fix peer deleting unique payment sent, received, dispute messages
This commit is contained in:
parent
546e260cd0
commit
fc396f7478
@ -365,7 +365,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
||||
UUID.randomUUID().toString(),
|
||||
getSupportType(),
|
||||
updatedMultisigHex,
|
||||
trade.getProcessModel().getPaymentSentMessage());
|
||||
trade.getArbitrator().getPaymentSentMessage());
|
||||
log.info("Send {} to peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
|
||||
"chatMessage.uid={}",
|
||||
disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress,
|
||||
@ -647,7 +647,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
||||
UUID.randomUUID().toString(),
|
||||
getSupportType(),
|
||||
updatedMultisigHex,
|
||||
trade.getProcessModel().getPaymentSentMessage());
|
||||
trade.getArbitrator().getPaymentSentMessage());
|
||||
|
||||
log.info("Send {} to peer {}. tradeId={}, peerOpenedDisputeMessage.uid={}, chatMessage.uid={}",
|
||||
peerOpenedDisputeMessage.getClass().getSimpleName(), peersNodeAddress,
|
||||
|
@ -224,13 +224,13 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
|
||||
else DisputeSummaryVerification.verifySignature(summaryText, arbitratorManager); // verify using registered arbitrator (will fail is arbitrator is unregistered)
|
||||
|
||||
// save dispute closed message for reprocessing
|
||||
trade.getProcessModel().setDisputeClosedMessage(disputeClosedMessage);
|
||||
trade.getArbitrator().setDisputeClosedMessage(disputeClosedMessage);
|
||||
requestPersistence();
|
||||
|
||||
// verify arbitrator does not receive DisputeClosedMessage
|
||||
if (keyRing.getPubKeyRing().equals(dispute.getAgentPubKeyRing())) {
|
||||
log.error("Arbitrator received disputeResultMessage. That should never happen.");
|
||||
trade.getProcessModel().setDisputeClosedMessage(null); // don't reprocess
|
||||
trade.getArbitrator().setDisputeClosedMessage(null); // don't reprocess
|
||||
return;
|
||||
}
|
||||
|
||||
@ -303,14 +303,14 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
|
||||
|
||||
// nack bad message and do not reprocess
|
||||
if (e instanceof IllegalArgumentException) {
|
||||
trade.getProcessModel().setPaymentReceivedMessage(null); // message is processed
|
||||
trade.getArbitrator().setDisputeClosedMessage(null); // message is processed
|
||||
sendAckMessage(chatMessage, dispute.getAgentPubKeyRing(), false, e.getMessage());
|
||||
requestPersistence();
|
||||
throw e;
|
||||
}
|
||||
|
||||
// schedule to reprocess message unless deleted
|
||||
if (trade.getProcessModel().getDisputeClosedMessage() != null) {
|
||||
if (trade.getArbitrator().getDisputeClosedMessage() != null) {
|
||||
if (!reprocessDisputeClosedMessageCounts.containsKey(trade.getId())) reprocessDisputeClosedMessageCounts.put(trade.getId(), 0);
|
||||
UserThread.runAfter(() -> {
|
||||
reprocessDisputeClosedMessageCounts.put(trade.getId(), reprocessDisputeClosedMessageCounts.get(trade.getId()) + 1); // increment reprocess count
|
||||
@ -325,12 +325,12 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
|
||||
synchronized (trade) {
|
||||
|
||||
// skip if no need to reprocess
|
||||
if (trade.isArbitrator() || trade.getProcessModel().getDisputeClosedMessage() == null || trade.getProcessModel().getDisputeClosedMessage().getUnsignedPayoutTxHex() == null || trade.getDisputeState().ordinal() >= Trade.DisputeState.DISPUTE_CLOSED.ordinal()) {
|
||||
if (trade.isArbitrator() || trade.getArbitrator().getDisputeClosedMessage() == null || trade.getArbitrator().getDisputeClosedMessage().getUnsignedPayoutTxHex() == null || trade.getDisputeState().ordinal() >= Trade.DisputeState.DISPUTE_CLOSED.ordinal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.warn("Reprocessing dispute closed message for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||
new Thread(() -> handleDisputeClosedMessage(trade.getProcessModel().getDisputeClosedMessage(), reprocessOnError)).start();
|
||||
new Thread(() -> handleDisputeClosedMessage(trade.getArbitrator().getDisputeClosedMessage(), reprocessOnError)).start();
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,7 +343,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
|
||||
Dispute dispute = disputeOptional.get();
|
||||
Contract contract = dispute.getContract();
|
||||
DisputeResult disputeResult = dispute.getDisputeResultProperty().get();
|
||||
String unsignedPayoutTxHex = trade.getProcessModel().getDisputeClosedMessage().getUnsignedPayoutTxHex();
|
||||
String unsignedPayoutTxHex = trade.getArbitrator().getDisputeClosedMessage().getUnsignedPayoutTxHex();
|
||||
|
||||
// Offer offer = checkNotNull(trade.getOffer(), "offer must not be null");
|
||||
// BigInteger sellerDepositAmount = multisigWallet.getTx(trade instanceof MakerTrade ? trade.getMaker().getDepositTxHash() : trade.getTaker().getDepositTxHash()).getIncomingAmount(); // TODO (woodser): use contract instead of trade to get deposit tx ids when contract has deposit tx ids
|
||||
@ -420,10 +420,10 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
|
||||
// determine if we already signed dispute payout tx
|
||||
// TODO: better way, such as by saving signed dispute payout tx hex in designated field instead of shared payoutTxHex field?
|
||||
Set<String> nonSignedDisputePayoutTxHexes = new HashSet<String>();
|
||||
if (trade.getProcessModel().getPaymentSentMessage() != null) nonSignedDisputePayoutTxHexes.add(trade.getProcessModel().getPaymentSentMessage().getPayoutTxHex());
|
||||
if (trade.getProcessModel().getPaymentReceivedMessage() != null) {
|
||||
nonSignedDisputePayoutTxHexes.add(trade.getProcessModel().getPaymentReceivedMessage().getUnsignedPayoutTxHex());
|
||||
nonSignedDisputePayoutTxHexes.add(trade.getProcessModel().getPaymentReceivedMessage().getSignedPayoutTxHex());
|
||||
if (trade.getTradePeer().getPaymentSentMessage() != null) nonSignedDisputePayoutTxHexes.add(trade.getTradePeer().getPaymentSentMessage().getPayoutTxHex());
|
||||
if (trade.getTradePeer().getPaymentReceivedMessage() != null) {
|
||||
nonSignedDisputePayoutTxHexes.add(trade.getTradePeer().getPaymentReceivedMessage().getUnsignedPayoutTxHex());
|
||||
nonSignedDisputePayoutTxHexes.add(trade.getTradePeer().getPaymentReceivedMessage().getSignedPayoutTxHex());
|
||||
}
|
||||
boolean signed = trade.getPayoutTxHex() != null && !nonSignedDisputePayoutTxHexes.contains(trade.getPayoutTxHex());
|
||||
|
||||
|
@ -1859,7 +1859,7 @@ public abstract class Trade implements Tradable, Model {
|
||||
if (isDepositsUnlocked() && !isPayoutPublished()) wallet.rescanSpent();
|
||||
|
||||
// get txs from trade wallet
|
||||
boolean payoutExpected = isPaymentReceived() || processModel.getPaymentReceivedMessage() != null || disputeState.ordinal() > DisputeState.ARBITRATOR_SENT_DISPUTE_CLOSED_MSG.ordinal() || processModel.getDisputeClosedMessage() != null;
|
||||
boolean payoutExpected = isPaymentReceived() || getSeller().getPaymentReceivedMessage() != null || disputeState.ordinal() >= DisputeState.ARBITRATOR_SENT_DISPUTE_CLOSED_MSG.ordinal() || getArbitrator().getDisputeClosedMessage() != null;
|
||||
boolean checkPool = !isDepositsConfirmed() || (!isPayoutConfirmed() && payoutExpected);
|
||||
MoneroTxQuery query = new MoneroTxQuery().setIncludeOutputs(true);
|
||||
if (!checkPool) query.setInTxPool(false); // avoid pool check if possible
|
||||
|
@ -18,7 +18,6 @@
|
||||
package haveno.core.trade.protocol;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import haveno.common.app.Version;
|
||||
import haveno.common.crypto.KeyRing;
|
||||
import haveno.common.crypto.PubKeyRing;
|
||||
import haveno.common.proto.ProtoUtil;
|
||||
@ -34,12 +33,9 @@ import haveno.core.payment.payload.PaymentAccountPayload;
|
||||
import haveno.core.proto.CoreProtoResolver;
|
||||
import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
|
||||
import haveno.core.support.dispute.mediation.mediator.MediatorManager;
|
||||
import haveno.core.support.dispute.messages.DisputeClosedMessage;
|
||||
import haveno.core.support.dispute.refund.refundagent.RefundAgentManager;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.TradeManager;
|
||||
import haveno.core.trade.messages.PaymentReceivedMessage;
|
||||
import haveno.core.trade.messages.PaymentSentMessage;
|
||||
import haveno.core.trade.messages.TradeMessage;
|
||||
import haveno.core.trade.statistics.ReferralIdService;
|
||||
import haveno.core.trade.statistics.TradeStatisticsManager;
|
||||
@ -139,18 +135,6 @@ public class ProcessModel implements Model, PersistablePayload {
|
||||
@Getter
|
||||
@Setter
|
||||
private String multisigAddress;
|
||||
@Nullable
|
||||
@Setter
|
||||
@Getter
|
||||
private PaymentSentMessage paymentSentMessage;
|
||||
@Nullable
|
||||
@Setter
|
||||
@Getter
|
||||
private PaymentReceivedMessage paymentReceivedMessage;
|
||||
@Nullable
|
||||
@Setter
|
||||
@Getter
|
||||
private DisputeClosedMessage disputeClosedMessage;
|
||||
|
||||
// We want to indicate the user the state of the message delivery of the
|
||||
// PaymentSentMessage. As well we do an automatic re-send in case it was not ACKed yet.
|
||||
@ -204,9 +188,6 @@ public class ProcessModel implements Model, PersistablePayload {
|
||||
Optional.ofNullable(mediatedPayoutTxSignature).ifPresent(e -> builder.setMediatedPayoutTxSignature(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(multisigAddress).ifPresent(e -> builder.setMultisigAddress(multisigAddress));
|
||||
Optional.ofNullable(paymentSentMessage).ifPresent(e -> builder.setPaymentSentMessage(paymentSentMessage.toProtoNetworkEnvelope().getPaymentSentMessage()));
|
||||
Optional.ofNullable(paymentReceivedMessage).ifPresent(e -> builder.setPaymentReceivedMessage(paymentReceivedMessage.toProtoNetworkEnvelope().getPaymentReceivedMessage()));
|
||||
Optional.ofNullable(disputeClosedMessage).ifPresent(e -> builder.setDisputeClosedMessage(disputeClosedMessage.toProtoNetworkEnvelope().getDisputeClosedMessage()));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@ -232,9 +213,6 @@ public class ProcessModel implements Model, PersistablePayload {
|
||||
MessageState paymentSentMessageState = ProtoUtil.enumFromProto(MessageState.class, paymentSentMessageStateString);
|
||||
processModel.setPaymentSentMessageState(paymentSentMessageState);
|
||||
|
||||
processModel.setPaymentSentMessage(proto.hasPaymentSentMessage() ? PaymentSentMessage.fromProto(proto.getPaymentSentMessage(), Version.getP2PMessageVersion()) : null);
|
||||
processModel.setPaymentReceivedMessage(proto.hasPaymentReceivedMessage() ? PaymentReceivedMessage.fromProto(proto.getPaymentReceivedMessage(), Version.getP2PMessageVersion()) : null);
|
||||
processModel.setDisputeClosedMessage(proto.hasDisputeClosedMessage() ? DisputeClosedMessage.fromProto(proto.getDisputeClosedMessage(), Version.getP2PMessageVersion()) : null);
|
||||
return processModel;
|
||||
}
|
||||
|
||||
|
@ -19,12 +19,16 @@ package haveno.core.trade.protocol;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Message;
|
||||
import haveno.common.app.Version;
|
||||
import haveno.common.crypto.PubKeyRing;
|
||||
import haveno.common.proto.ProtoUtil;
|
||||
import haveno.common.proto.persistable.PersistablePayload;
|
||||
import haveno.core.account.witness.AccountAgeWitness;
|
||||
import haveno.core.payment.payload.PaymentAccountPayload;
|
||||
import haveno.core.proto.CoreProtoResolver;
|
||||
import haveno.core.support.dispute.messages.DisputeClosedMessage;
|
||||
import haveno.core.trade.messages.PaymentReceivedMessage;
|
||||
import haveno.core.trade.messages.PaymentSentMessage;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@ -79,6 +83,19 @@ public final class TradePeer implements PersistablePayload {
|
||||
private String contractAsJson;
|
||||
@Nullable
|
||||
private byte[] contractSignature;
|
||||
@Nullable
|
||||
@Setter
|
||||
@Getter
|
||||
private PaymentSentMessage paymentSentMessage;
|
||||
@Nullable
|
||||
@Setter
|
||||
@Getter
|
||||
private PaymentReceivedMessage paymentReceivedMessage;
|
||||
@Nullable
|
||||
@Setter
|
||||
@Getter
|
||||
private DisputeClosedMessage disputeClosedMessage;
|
||||
|
||||
|
||||
// added in v 0.6
|
||||
@Nullable
|
||||
@ -164,6 +181,9 @@ public final class TradePeer implements PersistablePayload {
|
||||
Optional.ofNullable(accountAgeWitnessSignature).ifPresent(e -> builder.setAccountAgeWitnessSignature(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(accountAgeWitness).ifPresent(e -> builder.setAccountAgeWitness(accountAgeWitness.toProtoAccountAgeWitness()));
|
||||
Optional.ofNullable(mediatedPayoutTxSignature).ifPresent(e -> builder.setMediatedPayoutTxSignature(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(paymentSentMessage).ifPresent(e -> builder.setPaymentSentMessage(paymentSentMessage.toProtoNetworkEnvelope().getPaymentSentMessage()));
|
||||
Optional.ofNullable(paymentReceivedMessage).ifPresent(e -> builder.setPaymentReceivedMessage(paymentReceivedMessage.toProtoNetworkEnvelope().getPaymentReceivedMessage()));
|
||||
Optional.ofNullable(disputeClosedMessage).ifPresent(e -> builder.setDisputeClosedMessage(disputeClosedMessage.toProtoNetworkEnvelope().getDisputeClosedMessage()));
|
||||
Optional.ofNullable(reserveTxHash).ifPresent(e -> builder.setReserveTxHash(reserveTxHash));
|
||||
Optional.ofNullable(reserveTxHex).ifPresent(e -> builder.setReserveTxHex(reserveTxHex));
|
||||
Optional.ofNullable(reserveTxKey).ifPresent(e -> builder.setReserveTxKey(reserveTxKey));
|
||||
@ -207,6 +227,9 @@ public final class TradePeer implements PersistablePayload {
|
||||
tradePeer.setAccountAgeWitness(protoAccountAgeWitness.getHash().isEmpty() ? null : AccountAgeWitness.fromProto(protoAccountAgeWitness));
|
||||
tradePeer.setCurrentDate(proto.getCurrentDate());
|
||||
tradePeer.setMediatedPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMediatedPayoutTxSignature()));
|
||||
tradePeer.setPaymentSentMessage(proto.hasPaymentSentMessage() ? PaymentSentMessage.fromProto(proto.getPaymentSentMessage(), Version.getP2PMessageVersion()) : null);
|
||||
tradePeer.setPaymentReceivedMessage(proto.hasPaymentReceivedMessage() ? PaymentReceivedMessage.fromProto(proto.getPaymentReceivedMessage(), Version.getP2PMessageVersion()) : null);
|
||||
tradePeer.setDisputeClosedMessage(proto.hasDisputeClosedMessage() ? DisputeClosedMessage.fromProto(proto.getDisputeClosedMessage(), Version.getP2PMessageVersion()) : null);
|
||||
tradePeer.setReserveTxHash(ProtoUtil.stringOrNullFromProto(proto.getReserveTxHash()));
|
||||
tradePeer.setReserveTxHex(ProtoUtil.stringOrNullFromProto(proto.getReserveTxHex()));
|
||||
tradePeer.setReserveTxKey(ProtoUtil.stringOrNullFromProto(proto.getReserveTxKey()));
|
||||
|
@ -274,12 +274,12 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||
synchronized (trade) {
|
||||
|
||||
// skip if no need to reprocess
|
||||
if (trade.isSeller() || trade.getProcessModel().getPaymentReceivedMessage() == null || trade.getState().ordinal() >= Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal()) {
|
||||
if (trade.isSeller() || trade.getSeller().getPaymentReceivedMessage() == null || trade.getState().ordinal() >= Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.warn("Reprocessing payment received message for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||
new Thread(() -> handle(trade.getProcessModel().getPaymentReceivedMessage(), trade.getProcessModel().getPaymentReceivedMessage().getSenderNodeAddress(), reprocessOnError)).start();
|
||||
new Thread(() -> handle(trade.getSeller().getPaymentReceivedMessage(), trade.getSeller().getPaymentReceivedMessage().getSenderNodeAddress(), reprocessOnError)).start();
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,7 +552,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||
processModel.getTradeManager().requestPersistence();
|
||||
|
||||
// schedule to reprocess message unless deleted
|
||||
if (trade.getProcessModel().getPaymentReceivedMessage() != null) {
|
||||
if (trade.getSeller().getPaymentReceivedMessage() != null) {
|
||||
UserThread.runAfter(() -> {
|
||||
reprocessPaymentReceivedMessageCount++;
|
||||
maybeReprocessPaymentReceivedMessage(reprocessOnError);
|
||||
|
@ -45,9 +45,9 @@ public class BuyerPreparePaymentSentMessage extends TradeTask {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
// skip if already created
|
||||
if (processModel.getPaymentSentMessage() != null) {
|
||||
log.warn("Skipping preparation of payment sent message since it's already created for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||
// skip if payout tx already created
|
||||
if (trade.getPayoutTxHex() != null) {
|
||||
log.warn("Skipping preparation of payment sent message because payout tx is already created for {} {}", trade.getClass().getSimpleName(), trade.getId());
|
||||
complete();
|
||||
return;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.messages.PaymentSentMessage;
|
||||
import haveno.core.trade.messages.TradeMailboxMessage;
|
||||
import haveno.core.trade.protocol.TradePeer;
|
||||
import haveno.core.util.JsonUtil;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
@ -56,9 +57,17 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
protected abstract NodeAddress getReceiverNodeAddress();
|
||||
protected abstract TradePeer getReceiver();
|
||||
|
||||
protected abstract PubKeyRing getReceiverPubKeyRing();
|
||||
@Override
|
||||
protected NodeAddress getReceiverNodeAddress() {
|
||||
return getReceiver().getNodeAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PubKeyRing getReceiverPubKeyRing() {
|
||||
return getReceiver().getPubKeyRing();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
@ -72,7 +81,7 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
|
||||
|
||||
@Override
|
||||
protected TradeMailboxMessage getTradeMailboxMessage(String tradeId) {
|
||||
if (processModel.getPaymentSentMessage() == null) {
|
||||
if (getReceiver().getPaymentSentMessage() == null) {
|
||||
|
||||
// We do not use a real unique ID here as we want to be able to re-send the exact same message in case the
|
||||
// peer does not respond with an ACK msg in a certain time interval. To avoid that we get dangling mailbox
|
||||
@ -98,13 +107,13 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
|
||||
String messageAsJson = JsonUtil.objectToJson(message);
|
||||
byte[] sig = HavenoUtils.sign(processModel.getP2PService().getKeyRing(), messageAsJson);
|
||||
message.setBuyerSignature(sig);
|
||||
processModel.setPaymentSentMessage(message);
|
||||
getReceiver().setPaymentSentMessage(message);
|
||||
trade.requestPersistence();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException (e);
|
||||
}
|
||||
}
|
||||
return processModel.getPaymentSentMessage();
|
||||
return getReceiver().getPaymentSentMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,10 +17,9 @@
|
||||
|
||||
package haveno.core.trade.protocol.tasks;
|
||||
|
||||
import haveno.common.crypto.PubKeyRing;
|
||||
import haveno.common.taskrunner.TaskRunner;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import haveno.core.trade.protocol.TradePeer;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ -32,12 +31,9 @@ public class BuyerSendPaymentSentMessageToArbitrator extends BuyerSendPaymentSen
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
protected NodeAddress getReceiverNodeAddress() {
|
||||
return trade.getArbitrator().getNodeAddress();
|
||||
}
|
||||
|
||||
protected PubKeyRing getReceiverPubKeyRing() {
|
||||
return trade.getArbitrator().getPubKeyRing();
|
||||
@Override
|
||||
protected TradePeer getReceiver() {
|
||||
return trade.getArbitrator();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,11 +17,10 @@
|
||||
|
||||
package haveno.core.trade.protocol.tasks;
|
||||
|
||||
import haveno.common.crypto.PubKeyRing;
|
||||
import haveno.common.taskrunner.TaskRunner;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.messages.TradeMessage;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import haveno.core.trade.protocol.TradePeer;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ -33,12 +32,9 @@ public class BuyerSendPaymentSentMessageToSeller extends BuyerSendPaymentSentMes
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
protected NodeAddress getReceiverNodeAddress() {
|
||||
return trade.getSeller().getNodeAddress();
|
||||
}
|
||||
|
||||
protected PubKeyRing getReceiverPubKeyRing() {
|
||||
return trade.getSeller().getPubKeyRing();
|
||||
@Override
|
||||
protected TradePeer getReceiver() {
|
||||
return trade.getSeller();
|
||||
}
|
||||
|
||||
// continue execution on fault so payment sent message is sent to arbitrator
|
||||
|
@ -26,6 +26,7 @@ import haveno.core.trade.BuyerTrade;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.messages.PaymentReceivedMessage;
|
||||
import haveno.core.trade.messages.PaymentSentMessage;
|
||||
import haveno.core.util.Validator;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -65,13 +66,13 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
||||
}
|
||||
|
||||
// save message for reprocessing
|
||||
processModel.setPaymentReceivedMessage(message);
|
||||
trade.requestPersistence();
|
||||
trade.getSeller().setPaymentReceivedMessage(message);
|
||||
|
||||
// set state
|
||||
trade.getSeller().setUpdatedMultisigHex(message.getUpdatedMultisigHex());
|
||||
trade.getBuyer().setUpdatedMultisigHex(message.getPaymentSentMessage().getUpdatedMultisigHex());
|
||||
trade.getBuyer().setAccountAgeWitness(message.getBuyerAccountAgeWitness());
|
||||
trade.requestPersistence();
|
||||
|
||||
// close open disputes
|
||||
if (trade.getDisputeState().ordinal() >= Trade.DisputeState.DISPUTE_REQUESTED.ordinal()) {
|
||||
@ -100,7 +101,7 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
||||
|
||||
// do not reprocess illegal argument
|
||||
if (t instanceof IllegalArgumentException) {
|
||||
processModel.setPaymentReceivedMessage(null); // do not reprocess
|
||||
trade.getSeller().setPaymentReceivedMessage(null); // do not reprocess
|
||||
trade.requestPersistence();
|
||||
}
|
||||
|
||||
@ -134,8 +135,9 @@ public class ProcessPaymentReceivedMessage extends TradeTask {
|
||||
trade.verifyPayoutTx(message.getSignedPayoutTxHex(), false, true);
|
||||
} else {
|
||||
try {
|
||||
if (trade.getProcessModel().getPaymentSentMessage() == null) throw new RuntimeException("Process model does not have payment sent message for " + trade.getClass().getSimpleName() + " " + trade.getId());
|
||||
if (StringUtils.equals(trade.getPayoutTxHex(), trade.getProcessModel().getPaymentSentMessage().getPayoutTxHex())) { // unsigned
|
||||
PaymentSentMessage paymentSentMessage = (trade.isArbitrator() ? trade.getBuyer() : trade.getArbitrator()).getPaymentSentMessage();
|
||||
if (paymentSentMessage == null) throw new RuntimeException("Process model does not have payment sent message for " + trade.getClass().getSimpleName() + " " + trade.getId());
|
||||
if (StringUtils.equals(trade.getPayoutTxHex(), paymentSentMessage.getPayoutTxHex())) { // unsigned
|
||||
log.info("{} {} verifying, signing, and publishing seller's payout tx", trade.getClass().getSimpleName(), trade.getId());
|
||||
trade.verifyPayoutTx(message.getUnsignedPayoutTxHex(), true, true);
|
||||
} else {
|
||||
|
@ -48,7 +48,7 @@ public class ProcessPaymentSentMessage extends TradeTask {
|
||||
trade.getBuyer().setNodeAddress(processModel.getTempTradePeerNodeAddress());
|
||||
|
||||
// update state from message
|
||||
processModel.setPaymentSentMessage(message);
|
||||
trade.getBuyer().setPaymentSentMessage(message);
|
||||
trade.setPayoutTxHex(message.getPayoutTxHex());
|
||||
trade.getBuyer().setUpdatedMultisigHex(message.getUpdatedMultisigHex());
|
||||
trade.getSeller().setAccountAgeWitness(message.getSellerAccountAgeWitness());
|
||||
|
@ -39,7 +39,7 @@ public class SellerPreparePaymentReceivedMessage extends TradeTask {
|
||||
trade.checkDaemonConnection();
|
||||
|
||||
// handle first time preparation
|
||||
if (processModel.getPaymentReceivedMessage() == null) {
|
||||
if (trade.getArbitrator().getPaymentReceivedMessage() == null) {
|
||||
|
||||
// import multisig hex
|
||||
trade.importMultisigHex();
|
||||
@ -56,11 +56,11 @@ public class SellerPreparePaymentReceivedMessage extends TradeTask {
|
||||
} else {
|
||||
createUnsignedPayoutTx();
|
||||
}
|
||||
} else if (processModel.getPaymentReceivedMessage().getSignedPayoutTxHex() != null && !trade.isPayoutPublished()) {
|
||||
} else if (trade.getArbitrator().getPaymentReceivedMessage().getSignedPayoutTxHex() != null && !trade.isPayoutPublished()) {
|
||||
|
||||
// republish payout tx from previous message
|
||||
log.info("Seller re-verifying and publishing payout tx for trade {}", trade.getId());
|
||||
trade.verifyPayoutTx(processModel.getPaymentReceivedMessage().getSignedPayoutTxHex(), false, true);
|
||||
trade.verifyPayoutTx(trade.getArbitrator().getPaymentReceivedMessage().getSignedPayoutTxHex(), false, true);
|
||||
}
|
||||
|
||||
processModel.getTradeManager().requestPersistence();
|
||||
|
@ -27,6 +27,7 @@ import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.messages.PaymentReceivedMessage;
|
||||
import haveno.core.trade.messages.TradeMailboxMessage;
|
||||
import haveno.core.trade.protocol.TradePeer;
|
||||
import haveno.core.util.JsonUtil;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@ -37,16 +38,23 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@Slf4j
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask {
|
||||
PaymentReceivedMessage message = null;
|
||||
SignedWitness signedWitness = null;
|
||||
|
||||
public SellerSendPaymentReceivedMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
protected abstract NodeAddress getReceiverNodeAddress();
|
||||
protected abstract TradePeer getReceiver();
|
||||
|
||||
protected abstract PubKeyRing getReceiverPubKeyRing();
|
||||
@Override
|
||||
protected NodeAddress getReceiverNodeAddress() {
|
||||
return getReceiver().getNodeAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PubKeyRing getReceiverPubKeyRing() {
|
||||
return getReceiver().getPubKeyRing();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
@ -61,7 +69,7 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag
|
||||
@Override
|
||||
protected TradeMailboxMessage getTradeMailboxMessage(String tradeId) {
|
||||
checkNotNull(trade.getPayoutTxHex(), "Payout tx must not be null");
|
||||
if (message == null) {
|
||||
if (getReceiver().getPaymentReceivedMessage() == null) {
|
||||
|
||||
// sign account witness
|
||||
AccountAgeWitnessService accountAgeWitnessService = processModel.getAccountAgeWitnessService();
|
||||
@ -75,7 +83,7 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag
|
||||
// messages where only the one which gets processed by the peer would be removed we use the same uid. All
|
||||
// other data stays the same when we re-send the message at any time later.
|
||||
String deterministicId = HavenoUtils.getDeterministicId(trade, PaymentReceivedMessage.class, getReceiverNodeAddress());
|
||||
message = new PaymentReceivedMessage(
|
||||
PaymentReceivedMessage message = new PaymentReceivedMessage(
|
||||
tradeId,
|
||||
processModel.getMyNodeAddress(),
|
||||
deterministicId,
|
||||
@ -85,7 +93,7 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag
|
||||
trade.getState().ordinal() >= Trade.State.SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG.ordinal(), // informs to expect payout
|
||||
trade.getTradePeer().getAccountAgeWitness(),
|
||||
signedWitness,
|
||||
processModel.getPaymentSentMessage()
|
||||
trade.getBuyer().getPaymentSentMessage()
|
||||
);
|
||||
|
||||
// sign message
|
||||
@ -93,13 +101,13 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag
|
||||
String messageAsJson = JsonUtil.objectToJson(message);
|
||||
byte[] sig = Sig.sign(processModel.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), messageAsJson.getBytes(Charsets.UTF_8));
|
||||
message.setSellerSignature(sig);
|
||||
processModel.setPaymentReceivedMessage(message);
|
||||
getReceiver().setPaymentReceivedMessage(message);
|
||||
trade.requestPersistence();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
return getReceiver().getPaymentReceivedMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,10 +17,9 @@
|
||||
|
||||
package haveno.core.trade.protocol.tasks;
|
||||
|
||||
import haveno.common.crypto.PubKeyRing;
|
||||
import haveno.common.taskrunner.TaskRunner;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import haveno.core.trade.protocol.TradePeer;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ -32,11 +31,8 @@ public class SellerSendPaymentReceivedMessageToArbitrator extends SellerSendPaym
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
protected NodeAddress getReceiverNodeAddress() {
|
||||
return trade.getArbitrator().getNodeAddress();
|
||||
}
|
||||
|
||||
protected PubKeyRing getReceiverPubKeyRing() {
|
||||
return trade.getArbitrator().getPubKeyRing();
|
||||
@Override
|
||||
protected TradePeer getReceiver() {
|
||||
return trade.getArbitrator();
|
||||
}
|
||||
}
|
||||
|
@ -17,13 +17,10 @@
|
||||
|
||||
package haveno.core.trade.protocol.tasks;
|
||||
|
||||
import haveno.common.crypto.PubKeyRing;
|
||||
import haveno.common.taskrunner.TaskRunner;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.messages.PaymentReceivedMessage;
|
||||
import haveno.core.trade.messages.TradeMailboxMessage;
|
||||
import haveno.core.trade.messages.TradeMessage;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import haveno.core.trade.protocol.TradePeer;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ -35,21 +32,9 @@ public class SellerSendPaymentReceivedMessageToBuyer extends SellerSendPaymentRe
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected TradeMailboxMessage getTradeMailboxMessage(String tradeId) {
|
||||
if (processModel.getPaymentReceivedMessage() == null) {
|
||||
processModel.setPaymentReceivedMessage((PaymentReceivedMessage) super.getTradeMailboxMessage(tradeId)); // save payment received message for buyer
|
||||
}
|
||||
return processModel.getPaymentReceivedMessage();
|
||||
}
|
||||
|
||||
protected NodeAddress getReceiverNodeAddress() {
|
||||
return trade.getBuyer().getNodeAddress();
|
||||
}
|
||||
|
||||
protected PubKeyRing getReceiverPubKeyRing() {
|
||||
return trade.getBuyer().getPubKeyRing();
|
||||
protected TradePeer getReceiver() {
|
||||
return trade.getBuyer();
|
||||
}
|
||||
|
||||
// continue execution on fault so payment received message is sent to arbitrator
|
||||
|
@ -1546,9 +1546,6 @@ message ProcessModel {
|
||||
TradePeer arbitrator = 11;
|
||||
NodeAddress temp_trade_peer_node_address = 12;
|
||||
string multisig_address = 13;
|
||||
PaymentSentMessage payment_sent_message = 14;
|
||||
PaymentReceivedMessage payment_received_message = 15;
|
||||
DisputeClosedMessage dispute_closed_message = 16;
|
||||
bytes mediated_payout_tx_signature = 17; // placeholder if mediation used in future
|
||||
int64 buyer_payout_amount_from_mediation = 18;
|
||||
int64 seller_payout_amount_from_mediation = 19;
|
||||
@ -1572,6 +1569,9 @@ message TradePeer {
|
||||
AccountAgeWitness account_age_witness = 20;
|
||||
int64 current_date = 21;
|
||||
bytes mediated_payout_tx_signature = 22;
|
||||
PaymentSentMessage payment_sent_message = 23;
|
||||
PaymentReceivedMessage payment_received_message = 24;
|
||||
DisputeClosedMessage dispute_closed_message = 25;
|
||||
|
||||
string reserve_tx_hash = 1001;
|
||||
string reserve_tx_hex = 1002;
|
||||
|
Loading…
Reference in New Issue
Block a user