use unique deterministic ids for mailbox messages

This commit is contained in:
woodser 2023-01-12 13:27:32 -05:00
parent 308f6e8077
commit 21fcdc7e00
6 changed files with 44 additions and 5 deletions

View file

@ -18,8 +18,10 @@
package bisq.core.trade;
import bisq.common.config.Config;
import bisq.common.crypto.Hash;
import bisq.common.crypto.PubKeyRing;
import bisq.common.crypto.Sig;
import bisq.common.util.Utilities;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferPayload;
import bisq.core.support.dispute.arbitration.ArbitrationManager;
@ -30,6 +32,7 @@ import bisq.core.trade.messages.PaymentSentMessage;
import bisq.core.util.JsonUtil;
import bisq.core.util.ParsingUtils;
import bisq.core.util.coin.CoinUtil;
import bisq.network.p2p.NodeAddress;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
@ -180,6 +183,19 @@ public class HavenoUtils {
}
}
/**
* Returns a unique deterministic id for sending a trade mailbox message.
*
* @param trade the trade
* @param tradeMessageClass the trade message class
* @param receiver the receiver address
* @return a unique deterministic id for sending a trade mailbox message
*/
public static String getDeterministicId(Trade trade, Class<?> tradeMessageClass, NodeAddress receiver) {
String uniqueId = trade.getId() + "_" + tradeMessageClass.getSimpleName() + "_" + trade.getRole() + "_to_" + trade.getPeerRole(trade.getTradingPeer(receiver));
return Utilities.bytesAsHexString(Hash.getSha256Ripemd160hash(uniqueId.getBytes(Charsets.UTF_8)));
}
/**
* Check if the arbitrator signature is valid for an offer.
*

View file

@ -1167,6 +1167,20 @@ public abstract class Trade implements Tradable, Model {
return null;
}
public String getRole() {
if (isBuyer()) return "Buyer";
if (isSeller()) return "Seller";
if (isArbitrator()) return "Arbitrator";
throw new IllegalArgumentException("Trade is not buyer, seller, or arbitrator");
}
public String getPeerRole(TradingPeer peer) {
if (peer == getBuyer()) return "Buyer";
if (peer == getSeller()) return "Seller";
if (peer == getArbitrator()) return "Arbitrator";
throw new IllegalArgumentException("Peer is not buyer, seller, or arbitrator");
}
public Date getTakeOfferDate() {
return new Date(takeOfferDate);
}

View file

@ -59,6 +59,7 @@ public final class PaymentReceivedMessage extends TradeMailboxMessage {
public PaymentReceivedMessage(String tradeId,
NodeAddress senderNodeAddress,
String uid,
String unsignedPayoutTxHex,
String signedPayoutTxHex,
String updatedMultisigHex,
@ -68,7 +69,7 @@ public final class PaymentReceivedMessage extends TradeMailboxMessage {
PaymentSentMessage paymentSentMessage) {
this(tradeId,
senderNodeAddress,
UUID.randomUUID().toString(),
uid,
Version.getP2PMessageVersion(),
unsignedPayoutTxHex,
signedPayoutTxHex,

View file

@ -18,6 +18,7 @@
package bisq.core.trade.protocol.tasks;
import bisq.core.network.MessageState;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.PaymentSentMessage;
import bisq.core.trade.messages.TradeMailboxMessage;
@ -78,7 +79,7 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask
// peer does not respond with an ACK msg in a certain time interval. To avoid that we get dangling mailbox
// 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 = tradeId + processModel.getMyNodeAddress().getFullAddress();
String deterministicId = HavenoUtils.getDeterministicId(trade, PaymentSentMessage.class, getReceiverNodeAddress());
// create payment sent message
PaymentSentMessage message = new PaymentSentMessage(

View file

@ -19,6 +19,7 @@ package bisq.core.trade.protocol.tasks;
import bisq.core.account.sign.SignedWitness;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.PaymentReceivedMessage;
import bisq.core.trade.messages.TradeMailboxMessage;
@ -71,10 +72,15 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag
log.info("{} {} signed and published peers account age witness", trade.getClass().getSimpleName(), trade.getId());
}
// TODO: create with deterministic id like BuyerSendPaymentSentMessage
// 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
// 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(
tradeId,
processModel.getMyNodeAddress(),
deterministicId,
trade.isPayoutPublished() ? null : trade.getPayoutTxHex(), // unsigned
trade.isPayoutPublished() ? trade.getPayoutTxHex() : null, // signed
trade.getSelf().getUpdatedMultisigHex(),

View file

@ -18,6 +18,7 @@
package bisq.core.trade.protocol.tasks;
import bisq.core.btc.wallet.XmrWalletService;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.trade.messages.DepositsConfirmedMessage;
import bisq.core.trade.messages.TradeMailboxMessage;
@ -71,13 +72,13 @@ public abstract class SendDepositsConfirmedMessage extends SendMailboxMessageTas
// peer does not respond with an ACK msg in a certain time interval. To avoid that we get dangling mailbox
// 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 = tradeId + processModel.getMyNodeAddress().getFullAddress();
String deterministicId = HavenoUtils.getDeterministicId(trade, DepositsConfirmedMessage.class, getReceiverNodeAddress());
message = new DepositsConfirmedMessage(
trade.getOffer().getId(),
processModel.getMyNodeAddress(),
processModel.getPubKeyRing(),
deterministicId,
getReceiverNodeAddress().equals(trade.getBuyer().getNodeAddress()) ? trade.getSeller().getPaymentAccountKey() : null, // buyer receives seller's payment account decryption key
trade.getBuyer() == trade.getTradingPeer(getReceiverNodeAddress()) ? trade.getSeller().getPaymentAccountKey() : null, // buyer receives seller's payment account decryption key
trade.getSelf().getUpdatedMultisigHex());
}
return message;