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:
woodser 2022-09-20 10:48:27 -04:00
parent c21ebe6a9d
commit d698555c9a
11 changed files with 33 additions and 21 deletions

View File

@ -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) {

View File

@ -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();

View File

@ -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) {

View File

@ -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()

View File

@ -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();

View File

@ -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());

View File

@ -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()
); );

View File

@ -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()
); );

View File

@ -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();

View File

@ -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();

View File

@ -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 {