trade completion fixes with payment key and multisig hex on confirmation
preserve peer multisig hex when arbitrator provides payment key process payment received using persistent, non-transient data payout_tx_published_msg represents payment_received_msg after payout update arbitrator's peer address on payout published schedule payment account key request after deposit request
This commit is contained in:
parent
c21ebe6a9d
commit
d698555c9a
@ -831,7 +831,6 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
// update trade state
|
// update trade state
|
||||||
getSelf().setPayoutTxHex(payoutTxHex);
|
getSelf().setPayoutTxHex(payoutTxHex);
|
||||||
setPayoutTx(describedTxSet.getTxs().get(0));
|
setPayoutTx(describedTxSet.getTxs().get(0));
|
||||||
setPayoutTxId(describedTxSet.getTxs().get(0).getHash());
|
|
||||||
|
|
||||||
// submit payout tx
|
// submit payout tx
|
||||||
if (publish) {
|
if (publish) {
|
||||||
|
@ -38,6 +38,7 @@ import javax.annotation.Nullable;
|
|||||||
@Value
|
@Value
|
||||||
public final class PayoutTxPublishedMessage extends TradeMailboxMessage {
|
public final class PayoutTxPublishedMessage extends TradeMailboxMessage {
|
||||||
private final NodeAddress senderNodeAddress;
|
private final NodeAddress senderNodeAddress;
|
||||||
|
private final boolean isMaker;
|
||||||
private final String signedPayoutTxHex;
|
private final String signedPayoutTxHex;
|
||||||
|
|
||||||
// Added in v1.4.0
|
// Added in v1.4.0
|
||||||
@ -46,10 +47,12 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage {
|
|||||||
|
|
||||||
public PayoutTxPublishedMessage(String tradeId,
|
public PayoutTxPublishedMessage(String tradeId,
|
||||||
NodeAddress senderNodeAddress,
|
NodeAddress senderNodeAddress,
|
||||||
|
boolean isMaker,
|
||||||
@Nullable SignedWitness signedWitness,
|
@Nullable SignedWitness signedWitness,
|
||||||
String signedPayoutTxHex) {
|
String signedPayoutTxHex) {
|
||||||
this(tradeId,
|
this(tradeId,
|
||||||
senderNodeAddress,
|
senderNodeAddress,
|
||||||
|
isMaker,
|
||||||
signedWitness,
|
signedWitness,
|
||||||
UUID.randomUUID().toString(),
|
UUID.randomUUID().toString(),
|
||||||
Version.getP2PMessageVersion(),
|
Version.getP2PMessageVersion(),
|
||||||
@ -63,12 +66,14 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage {
|
|||||||
|
|
||||||
private PayoutTxPublishedMessage(String tradeId,
|
private PayoutTxPublishedMessage(String tradeId,
|
||||||
NodeAddress senderNodeAddress,
|
NodeAddress senderNodeAddress,
|
||||||
|
boolean isMaker,
|
||||||
@Nullable SignedWitness signedWitness,
|
@Nullable SignedWitness signedWitness,
|
||||||
String uid,
|
String uid,
|
||||||
String messageVersion,
|
String messageVersion,
|
||||||
String signedPayoutTxHex) {
|
String signedPayoutTxHex) {
|
||||||
super(messageVersion, tradeId, uid);
|
super(messageVersion, tradeId, uid);
|
||||||
this.senderNodeAddress = senderNodeAddress;
|
this.senderNodeAddress = senderNodeAddress;
|
||||||
|
this.isMaker = isMaker;
|
||||||
this.signedWitness = signedWitness;
|
this.signedWitness = signedWitness;
|
||||||
this.signedPayoutTxHex = signedPayoutTxHex;
|
this.signedPayoutTxHex = signedPayoutTxHex;
|
||||||
}
|
}
|
||||||
@ -78,6 +83,7 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage {
|
|||||||
protobuf.PayoutTxPublishedMessage.Builder builder = protobuf.PayoutTxPublishedMessage.newBuilder()
|
protobuf.PayoutTxPublishedMessage.Builder builder = protobuf.PayoutTxPublishedMessage.newBuilder()
|
||||||
.setTradeId(tradeId)
|
.setTradeId(tradeId)
|
||||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||||
|
.setIsMaker(isMaker)
|
||||||
.setUid(uid)
|
.setUid(uid)
|
||||||
.setSignedPayoutTxHex(signedPayoutTxHex);
|
.setSignedPayoutTxHex(signedPayoutTxHex);
|
||||||
Optional.ofNullable(signedWitness).ifPresent(signedWitness -> builder.setSignedWitness(signedWitness.toProtoSignedWitness()));
|
Optional.ofNullable(signedWitness).ifPresent(signedWitness -> builder.setSignedWitness(signedWitness.toProtoSignedWitness()));
|
||||||
@ -93,6 +99,7 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage {
|
|||||||
null;
|
null;
|
||||||
return new PayoutTxPublishedMessage(proto.getTradeId(),
|
return new PayoutTxPublishedMessage(proto.getTradeId(),
|
||||||
NodeAddress.fromProto(proto.getSenderNodeAddress()),
|
NodeAddress.fromProto(proto.getSenderNodeAddress()),
|
||||||
|
proto.getIsMaker(),
|
||||||
signedWitness,
|
signedWitness,
|
||||||
proto.getUid(),
|
proto.getUid(),
|
||||||
messageVersion,
|
messageVersion,
|
||||||
@ -103,6 +110,7 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "PayoutTxPublishedMessage{" +
|
return "PayoutTxPublishedMessage{" +
|
||||||
"\n senderNodeAddress=" + senderNodeAddress +
|
"\n senderNodeAddress=" + senderNodeAddress +
|
||||||
|
",\n isMaker=" + isMaker +
|
||||||
",\n signedWitness=" + signedWitness +
|
",\n signedWitness=" + signedWitness +
|
||||||
",\n signedPayoutTxHex=" + signedPayoutTxHex +
|
",\n signedPayoutTxHex=" + signedPayoutTxHex +
|
||||||
"\n} " + super.toString();
|
"\n} " + super.toString();
|
||||||
|
@ -109,8 +109,8 @@ public abstract class BuyerProtocol extends DisputeProtocol {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSignContractResponse(SignContractResponse response, NodeAddress sender) {
|
public void handleSignContractResponse(SignContractResponse response, NodeAddress sender) {
|
||||||
sendPaymentAccountKeyRequestIfWhenNeeded(BuyerEvent.DEPOSIT_TXS_CONFIRMED, true);
|
|
||||||
super.handleSignContractResponse(response, sender);
|
super.handleSignContractResponse(response, sender);
|
||||||
|
sendPaymentAccountKeyRequestIfWhenNeeded(BuyerEvent.DEPOSIT_TXS_CONFIRMED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(PaymentAccountKeyResponse response, NodeAddress sender) {
|
public void handle(PaymentAccountKeyResponse response, NodeAddress sender) {
|
||||||
|
@ -40,6 +40,10 @@ public class ArbitratorProcessPayoutTxPublishedMessage extends TradeTask {
|
|||||||
// verify and publish payout tx
|
// verify and publish payout tx
|
||||||
trade.verifyPayoutTx(request.getSignedPayoutTxHex(), false, true);
|
trade.verifyPayoutTx(request.getSignedPayoutTxHex(), false, true);
|
||||||
|
|
||||||
|
// update latest peer address
|
||||||
|
if (request.isMaker()) trade.setMakerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
||||||
|
else trade.setTakerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
||||||
|
|
||||||
// TODO: publish signed witness data?
|
// TODO: publish signed witness data?
|
||||||
//request.getSignedWitness()
|
//request.getSignedWitness()
|
||||||
|
|
||||||
|
@ -41,18 +41,14 @@ public class BuyerProcessPaymentAccountKeyResponse extends TradeTask {
|
|||||||
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
// buyer may already have decrypted payment account payload from arbitrator request
|
|
||||||
if (trade.getTradingPeer().getPaymentAccountPayload() != null) {
|
|
||||||
complete();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// decrypt peer's payment account payload
|
// decrypt peer's payment account payload
|
||||||
PaymentAccountKeyResponse request = (PaymentAccountKeyResponse) processModel.getTradeMessage();
|
PaymentAccountKeyResponse request = (PaymentAccountKeyResponse) processModel.getTradeMessage();
|
||||||
|
if (trade.getTradingPeer().getPaymentAccountPayload() == null) {
|
||||||
trade.decryptPeersPaymentAccountPayload(request.getPaymentAccountKey());
|
trade.decryptPeersPaymentAccountPayload(request.getPaymentAccountKey());
|
||||||
|
}
|
||||||
|
|
||||||
// store updated multisig hex for processing on payment sent
|
// store updated multisig hex for processing on payment sent
|
||||||
trade.getTradingPeer().setUpdatedMultisigHex(request.getUpdatedMultisigHex());
|
if (request.getUpdatedMultisigHex() != null) trade.getTradingPeer().setUpdatedMultisigHex(request.getUpdatedMultisigHex());
|
||||||
|
|
||||||
// persist and complete
|
// persist and complete
|
||||||
processModel.getTradeManager().requestPersistence();
|
processModel.getTradeManager().requestPersistence();
|
||||||
|
@ -56,11 +56,11 @@ public class BuyerProcessPaymentReceivedMessage extends TradeTask {
|
|||||||
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
||||||
|
|
||||||
// handle if payout tx is not seen on network
|
// handle if payout tx is not seen on network
|
||||||
if (trade.getPayoutTx() == null) {
|
if (trade.getPhase().ordinal() < Trade.Phase.PAYOUT_PUBLISHED.ordinal()) {
|
||||||
|
|
||||||
// publish payout tx if signed. otherwise verify, sign, and publish payout tx
|
// publish payout tx if signed. otherwise verify, sign, and publish payout tx
|
||||||
boolean fullySigned = trade.getSelf().getPayoutTx() != null;
|
boolean previouslySigned = trade.getBuyer().getPayoutTxHex() != null;
|
||||||
if (fullySigned) {
|
if (previouslySigned) {
|
||||||
log.info("Buyer publishing signed payout tx from seller");
|
log.info("Buyer publishing signed payout tx from seller");
|
||||||
XmrWalletService walletService = processModel.getProvider().getXmrWalletService();
|
XmrWalletService walletService = processModel.getProvider().getXmrWalletService();
|
||||||
MoneroWallet multisigWallet = walletService.getMultisigWallet(trade.getId());
|
MoneroWallet multisigWallet = walletService.getMultisigWallet(trade.getId());
|
||||||
|
@ -54,6 +54,7 @@ public class BuyerSendPayoutTxPublishedMessage extends SendMailboxMessageTask {
|
|||||||
return new PayoutTxPublishedMessage(
|
return new PayoutTxPublishedMessage(
|
||||||
tradeId,
|
tradeId,
|
||||||
processModel.getMyNodeAddress(),
|
processModel.getMyNodeAddress(),
|
||||||
|
trade.isMaker(),
|
||||||
null, // TODO: send witness data?
|
null, // TODO: send witness data?
|
||||||
trade.getSelf().getPayoutTxHex()
|
trade.getSelf().getPayoutTxHex()
|
||||||
);
|
);
|
||||||
|
@ -69,6 +69,7 @@ public class SellerMaybeSendPayoutTxPublishedMessage extends SendMailboxMessageT
|
|||||||
return new PayoutTxPublishedMessage(
|
return new PayoutTxPublishedMessage(
|
||||||
tradeId,
|
tradeId,
|
||||||
processModel.getMyNodeAddress(),
|
processModel.getMyNodeAddress(),
|
||||||
|
trade.isMaker(),
|
||||||
null, // TODO: send witness data?
|
null, // TODO: send witness data?
|
||||||
trade.getSelf().getPayoutTxHex()
|
trade.getSelf().getPayoutTxHex()
|
||||||
);
|
);
|
||||||
|
@ -57,7 +57,7 @@ public class SellerProcessPaymentSentMessage extends TradeTask {
|
|||||||
walletService.closeMultisigWallet(trade.getId());
|
walletService.closeMultisigWallet(trade.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// update to the latest peer address of our peer if the message is correct // TODO (woodser): update to latest peer addresses where needed
|
// update latest peer address
|
||||||
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
||||||
|
|
||||||
String counterCurrencyTxId = message.getCounterCurrencyTxId();
|
String counterCurrencyTxId = message.getCounterCurrencyTxId();
|
||||||
|
@ -65,9 +65,11 @@ public class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: using PAYOUT_TX_PUBLISHED_MSG to represent PAYMENT_RECEIVED_MSG after payout, but PAYOUT_TX_PUBLISHED_MSG is specifically for arbitrator. delete *PAYOUT_TX_PUBLISHED* messages and check payout field manually?
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateSent() {
|
protected void setStateSent() {
|
||||||
trade.setState(trade.getState() == Trade.State.SELLER_PUBLISHED_PAYOUT_TX ? Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG);
|
trade.setState(trade.getState().ordinal() >= Trade.State.SELLER_PUBLISHED_PAYOUT_TX.ordinal() ? Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG);
|
||||||
log.info("Sent SellerReceivedPaymentMessage: tradeId={} at peer {} SignedWitness {}",
|
log.info("Sent SellerReceivedPaymentMessage: tradeId={} at peer {} SignedWitness {}",
|
||||||
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
||||||
processModel.getTradeManager().requestPersistence();
|
processModel.getTradeManager().requestPersistence();
|
||||||
@ -75,7 +77,7 @@ public class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateArrived() {
|
protected void setStateArrived() {
|
||||||
trade.setState(trade.getState() == Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG ? Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG);
|
trade.setState(trade.getState().ordinal() >= Trade.State.SELLER_PUBLISHED_PAYOUT_TX.ordinal() ? Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG);
|
||||||
log.info("Seller's PaymentReceivedMessage arrived: tradeId={} at peer {} SignedWitness {}",
|
log.info("Seller's PaymentReceivedMessage arrived: tradeId={} at peer {} SignedWitness {}",
|
||||||
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
||||||
processModel.getTradeManager().requestPersistence();
|
processModel.getTradeManager().requestPersistence();
|
||||||
@ -83,7 +85,7 @@ public class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateStoredInMailbox() {
|
protected void setStateStoredInMailbox() {
|
||||||
trade.setState(trade.getState() == Trade.State.SELLER_PUBLISHED_PAYOUT_TX ? Trade.State.SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG);
|
trade.setState(trade.getState().ordinal() >= Trade.State.SELLER_PUBLISHED_PAYOUT_TX.ordinal() ? Trade.State.SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG);
|
||||||
log.info("Seller's PaymentReceivedMessage stored in mailbox: tradeId={} at peer {} SignedWitness {}",
|
log.info("Seller's PaymentReceivedMessage stored in mailbox: tradeId={} at peer {} SignedWitness {}",
|
||||||
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
||||||
processModel.getTradeManager().requestPersistence();
|
processModel.getTradeManager().requestPersistence();
|
||||||
@ -91,7 +93,7 @@ public class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateFault() {
|
protected void setStateFault() {
|
||||||
trade.setState(trade.getState() == Trade.State.SELLER_PUBLISHED_PAYOUT_TX ? Trade.State.SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG);
|
trade.setState(trade.getState().ordinal() >= Trade.State.SELLER_PUBLISHED_PAYOUT_TX.ordinal() ? Trade.State.SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG);
|
||||||
log.error("SellerReceivedPaymentMessage failed: tradeId={} at peer {} SignedWitness {}",
|
log.error("SellerReceivedPaymentMessage failed: tradeId={} at peer {} SignedWitness {}",
|
||||||
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
||||||
processModel.getTradeManager().requestPersistence();
|
processModel.getTradeManager().requestPersistence();
|
||||||
|
@ -461,9 +461,10 @@ message PaymentReceivedMessage {
|
|||||||
message PayoutTxPublishedMessage {
|
message PayoutTxPublishedMessage {
|
||||||
string trade_id = 1;
|
string trade_id = 1;
|
||||||
NodeAddress sender_node_address = 2;
|
NodeAddress sender_node_address = 2;
|
||||||
string uid = 3;
|
bool is_maker = 3;
|
||||||
SignedWitness signed_witness = 4;
|
string uid = 4;
|
||||||
string signed_payout_tx_hex = 5;
|
SignedWitness signed_witness = 5;
|
||||||
|
string signed_payout_tx_hex = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ArbitratorPayoutTxRequest {
|
message ArbitratorPayoutTxRequest {
|
||||||
|
Loading…
Reference in New Issue
Block a user