mirror of
https://github.com/bisq-network/bisq.git
synced 2025-03-04 03:03:48 +01:00
Add listener on BuyerSendCounterCurrencyTransferStartedMessage to resend msg case it has not arrived
Add signed witness to PayoutTxPublishedMessage Remove usage of RefreshTradeStateRequest but leave it for backward compatibility Move removeMailboxMessageAfterProcessing calls in finally branch Rename methods
This commit is contained in:
parent
33c816acf6
commit
527f1537a9
26 changed files with 358 additions and 446 deletions
|
@ -216,20 +216,20 @@ public class SignedWitnessService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arbitrators sign with EC key
|
// Arbitrators sign with EC key
|
||||||
public void signAccountAgeWitness(Coin tradeAmount,
|
public void signAndPublishAccountAgeWitness(Coin tradeAmount,
|
||||||
AccountAgeWitness accountAgeWitness,
|
AccountAgeWitness accountAgeWitness,
|
||||||
ECKey key,
|
ECKey key,
|
||||||
PublicKey peersPubKey) {
|
PublicKey peersPubKey) {
|
||||||
signAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey.getEncoded(), new Date().getTime());
|
signAndPublishAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey.getEncoded(), new Date().getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arbitrators sign with EC key
|
// Arbitrators sign with EC key
|
||||||
public String signAccountAgeWitness(AccountAgeWitness accountAgeWitness,
|
public String signAndPublishAccountAgeWitness(AccountAgeWitness accountAgeWitness,
|
||||||
ECKey key,
|
ECKey key,
|
||||||
byte[] peersPubKey,
|
byte[] peersPubKey,
|
||||||
long time) {
|
long time) {
|
||||||
var witnessPubKey = peersPubKey == null ? ownerPubKey(accountAgeWitness) : peersPubKey;
|
var witnessPubKey = peersPubKey == null ? ownerPubKey(accountAgeWitness) : peersPubKey;
|
||||||
return signAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, key, witnessPubKey, time);
|
return signAndPublishAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, key, witnessPubKey, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arbitrators sign with EC key
|
// Arbitrators sign with EC key
|
||||||
|
@ -238,11 +238,11 @@ public class SignedWitnessService {
|
||||||
long childSignTime) {
|
long childSignTime) {
|
||||||
var time = childSignTime - SIGNER_AGE - 1;
|
var time = childSignTime - SIGNER_AGE - 1;
|
||||||
var dummyAccountAgeWitness = new AccountAgeWitness(Hash.getRipemd160hash(peersPubKey), time);
|
var dummyAccountAgeWitness = new AccountAgeWitness(Hash.getRipemd160hash(peersPubKey), time);
|
||||||
return signAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, dummyAccountAgeWitness, key, peersPubKey, time);
|
return signAndPublishAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, dummyAccountAgeWitness, key, peersPubKey, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arbitrators sign with EC key
|
// Arbitrators sign with EC key
|
||||||
private String signAccountAgeWitness(Coin tradeAmount,
|
private String signAndPublishAccountAgeWitness(Coin tradeAmount,
|
||||||
AccountAgeWitness accountAgeWitness,
|
AccountAgeWitness accountAgeWitness,
|
||||||
ECKey key,
|
ECKey key,
|
||||||
byte[] peersPubKey,
|
byte[] peersPubKey,
|
||||||
|
@ -272,14 +272,14 @@ public class SignedWitnessService {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selfSignAccountAgeWitness(AccountAgeWitness accountAgeWitness) throws CryptoException {
|
public void selfSignAndPublishAccountAgeWitness(AccountAgeWitness accountAgeWitness) throws CryptoException {
|
||||||
log.info("Sign own accountAgeWitness {}", accountAgeWitness);
|
log.info("Sign own accountAgeWitness {}", accountAgeWitness);
|
||||||
signAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness,
|
signAndPublishAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness,
|
||||||
keyRing.getSignatureKeyPair().getPublic());
|
keyRing.getSignatureKeyPair().getPublic());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any peer can sign with DSA key
|
// Any peer can sign with DSA key
|
||||||
public Optional<SignedWitness> signAccountAgeWitness(Coin tradeAmount,
|
public Optional<SignedWitness> signAndPublishAccountAgeWitness(Coin tradeAmount,
|
||||||
AccountAgeWitness accountAgeWitness,
|
AccountAgeWitness accountAgeWitness,
|
||||||
PublicKey peersPubKey) throws CryptoException {
|
PublicKey peersPubKey) throws CryptoException {
|
||||||
if (isSignedAccountAgeWitness(accountAgeWitness)) {
|
if (isSignedAccountAgeWitness(accountAgeWitness)) {
|
||||||
|
@ -494,7 +494,8 @@ public class SignedWitnessService {
|
||||||
private void publishSignedWitness(SignedWitness signedWitness) {
|
private void publishSignedWitness(SignedWitness signedWitness) {
|
||||||
if (!signedWitnessMap.containsKey(signedWitness.getHashAsByteArray())) {
|
if (!signedWitnessMap.containsKey(signedWitness.getHashAsByteArray())) {
|
||||||
log.info("broadcast signed witness {}", signedWitness.toString());
|
log.info("broadcast signed witness {}", signedWitness.toString());
|
||||||
p2PService.addPersistableNetworkPayload(signedWitness, false);
|
// We set reBroadcast to true to achieve better resilience.
|
||||||
|
p2PService.addPersistableNetworkPayload(signedWitness, true);
|
||||||
addToMap(signedWitness);
|
addToMap(signedWitness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,14 +35,11 @@ import bisq.core.support.dispute.DisputeResult;
|
||||||
import bisq.core.support.dispute.arbitration.TraderDataItem;
|
import bisq.core.support.dispute.arbitration.TraderDataItem;
|
||||||
import bisq.core.trade.Contract;
|
import bisq.core.trade.Contract;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.messages.TraderSignedWitnessMessage;
|
|
||||||
import bisq.core.trade.protocol.TradingPeer;
|
import bisq.core.trade.protocol.TradingPeer;
|
||||||
import bisq.core.user.User;
|
import bisq.core.user.User;
|
||||||
|
|
||||||
import bisq.network.p2p.BootstrapListener;
|
import bisq.network.p2p.BootstrapListener;
|
||||||
import bisq.network.p2p.NodeAddress;
|
|
||||||
import bisq.network.p2p.P2PService;
|
import bisq.network.p2p.P2PService;
|
||||||
import bisq.network.p2p.SendMailboxMessageListener;
|
|
||||||
import bisq.network.p2p.storage.P2PDataStorage;
|
import bisq.network.p2p.storage.P2PDataStorage;
|
||||||
import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService;
|
import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService;
|
||||||
|
|
||||||
|
@ -76,7 +73,6 @@ import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
@ -202,7 +198,7 @@ public class AccountAgeWitnessService {
|
||||||
|
|
||||||
private void onBootStrapped() {
|
private void onBootStrapped() {
|
||||||
republishAllFiatAccounts();
|
republishAllFiatAccounts();
|
||||||
signSameNameAccounts();
|
signAndPublishSameNameAccounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -643,7 +639,7 @@ public class AccountAgeWitnessService {
|
||||||
AccountAgeWitness accountAgeWitness,
|
AccountAgeWitness accountAgeWitness,
|
||||||
ECKey key,
|
ECKey key,
|
||||||
PublicKey peersPubKey) {
|
PublicKey peersPubKey) {
|
||||||
signedWitnessService.signAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey);
|
signedWitnessService.signAndPublishAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String arbitratorSignOrphanWitness(AccountAgeWitness accountAgeWitness,
|
public String arbitratorSignOrphanWitness(AccountAgeWitness accountAgeWitness,
|
||||||
|
@ -655,7 +651,7 @@ public class AccountAgeWitnessService {
|
||||||
.findAny()
|
.findAny()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
checkNotNull(signedWitness);
|
checkNotNull(signedWitness);
|
||||||
return signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, signedWitness.getWitnessOwnerPubKey(),
|
return signedWitnessService.signAndPublishAccountAgeWitness(accountAgeWitness, key, signedWitness.getWitnessOwnerPubKey(),
|
||||||
time);
|
time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,10 +665,10 @@ public class AccountAgeWitnessService {
|
||||||
ECKey key,
|
ECKey key,
|
||||||
byte[] tradersPubKey,
|
byte[] tradersPubKey,
|
||||||
long time) {
|
long time) {
|
||||||
signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, tradersPubKey, time);
|
signedWitnessService.signAndPublishAccountAgeWitness(accountAgeWitness, key, tradersPubKey, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<SignedWitness> traderSignPeersAccountAgeWitness(Trade trade) {
|
public Optional<SignedWitness> traderSignAndPublishPeersAccountAgeWitness(Trade trade) {
|
||||||
AccountAgeWitness peersWitness = findTradePeerWitness(trade).orElse(null);
|
AccountAgeWitness peersWitness = findTradePeerWitness(trade).orElse(null);
|
||||||
Coin tradeAmount = trade.getTradeAmount();
|
Coin tradeAmount = trade.getTradeAmount();
|
||||||
checkNotNull(trade.getProcessModel().getTradingPeer().getPubKeyRing(), "Peer must have a keyring");
|
checkNotNull(trade.getProcessModel().getTradingPeer().getPubKeyRing(), "Peer must have a keyring");
|
||||||
|
@ -682,7 +678,7 @@ public class AccountAgeWitnessService {
|
||||||
checkNotNull(peersPubKey, "Peers pub key must not be null");
|
checkNotNull(peersPubKey, "Peers pub key must not be null");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return signedWitnessService.signAccountAgeWitness(tradeAmount, peersWitness, peersPubKey);
|
return signedWitnessService.signAndPublishAccountAgeWitness(tradeAmount, peersWitness, peersPubKey);
|
||||||
} catch (CryptoException e) {
|
} catch (CryptoException e) {
|
||||||
log.warn("Trader failed to sign witness, exception {}", e.toString());
|
log.warn("Trader failed to sign witness, exception {}", e.toString());
|
||||||
}
|
}
|
||||||
|
@ -827,7 +823,7 @@ public class AccountAgeWitnessService {
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void signSameNameAccounts() {
|
public void signAndPublishSameNameAccounts() {
|
||||||
// Collect accounts that have ownerId to sign unsigned accounts with the same ownderId
|
// Collect accounts that have ownerId to sign unsigned accounts with the same ownderId
|
||||||
var signerAccounts = Objects.requireNonNull(user.getPaymentAccounts()).stream()
|
var signerAccounts = Objects.requireNonNull(user.getPaymentAccounts()).stream()
|
||||||
.filter(account -> account.getOwnerId() != null &&
|
.filter(account -> account.getOwnerId() != null &&
|
||||||
|
@ -842,7 +838,7 @@ public class AccountAgeWitnessService {
|
||||||
signerAccounts.forEach(signer -> unsignedAccounts.forEach(unsigned -> {
|
signerAccounts.forEach(signer -> unsignedAccounts.forEach(unsigned -> {
|
||||||
if (signer.getOwnerId().equals(unsigned.getOwnerId())) {
|
if (signer.getOwnerId().equals(unsigned.getOwnerId())) {
|
||||||
try {
|
try {
|
||||||
signedWitnessService.selfSignAccountAgeWitness(
|
signedWitnessService.selfSignAndPublishAccountAgeWitness(
|
||||||
getMyWitness(unsigned.getPaymentAccountPayload()));
|
getMyWitness(unsigned.getPaymentAccountPayload()));
|
||||||
} catch (CryptoException e) {
|
} catch (CryptoException e) {
|
||||||
log.warn("Self signing failed, exception {}", e.toString());
|
log.warn("Self signing failed, exception {}", e.toString());
|
||||||
|
@ -868,44 +864,4 @@ public class AccountAgeWitnessService {
|
||||||
!peerHasSignedWitness(trade) &&
|
!peerHasSignedWitness(trade) &&
|
||||||
tradeAmountIsSufficient(trade.getTradeAmount());
|
tradeAmountIsSufficient(trade.getTradeAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void maybeSignWitness(Trade trade) {
|
|
||||||
if (isSignWitnessTrade(trade)) {
|
|
||||||
var signedWitnessOptional = traderSignPeersAccountAgeWitness(trade);
|
|
||||||
signedWitnessOptional.ifPresent(signedWitness -> sendSignedWitnessToPeer(signedWitness, trade));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendSignedWitnessToPeer(SignedWitness signedWitness, Trade trade) {
|
|
||||||
if (trade == null) return;
|
|
||||||
|
|
||||||
NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress();
|
|
||||||
var traderSignedWitnessMessage = new TraderSignedWitnessMessage(UUID.randomUUID().toString(), trade.getId(),
|
|
||||||
tradingPeerNodeAddress, signedWitness);
|
|
||||||
|
|
||||||
p2PService.sendEncryptedMailboxMessage(
|
|
||||||
tradingPeerNodeAddress,
|
|
||||||
trade.getProcessModel().getTradingPeer().getPubKeyRing(),
|
|
||||||
traderSignedWitnessMessage,
|
|
||||||
new SendMailboxMessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onArrived() {
|
|
||||||
log.info("SendMailboxMessageListener onArrived tradeId={} at peer {} SignedWitness {}",
|
|
||||||
trade.getId(), tradingPeerNodeAddress, signedWitness);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStoredInMailbox() {
|
|
||||||
log.info("SendMailboxMessageListener onStoredInMailbox tradeId={} at peer {} SignedWitness {}",
|
|
||||||
trade.getId(), tradingPeerNodeAddress, signedWitness);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFault(String errorMessage) {
|
|
||||||
log.error("SendMailboxMessageListener onFault tradeId={} at peer {} SignedWitness {}",
|
|
||||||
trade.getId(), tradingPeerNodeAddress, signedWitness);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,9 +350,6 @@ public class TradeManager implements PersistedDataHost {
|
||||||
ResultHandler resultHandler,
|
ResultHandler resultHandler,
|
||||||
ErrorMessageHandler errorMessageHandler) {
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
sellerTrade.onFiatPaymentReceived(resultHandler, errorMessageHandler);
|
sellerTrade.onFiatPaymentReceived(resultHandler, errorMessageHandler);
|
||||||
|
|
||||||
//TODO move to trade protocol task
|
|
||||||
accountAgeWitnessService.maybeSignWitness(sellerTrade);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initPendingTrade(Trade trade) {
|
private void initPendingTrade(Trade trade) {
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
package bisq.core.trade.messages;
|
package bisq.core.trade.messages;
|
||||||
|
|
||||||
|
import bisq.core.account.sign.SignedWitness;
|
||||||
|
|
||||||
import bisq.network.p2p.MailboxMessage;
|
import bisq.network.p2p.MailboxMessage;
|
||||||
import bisq.network.p2p.NodeAddress;
|
import bisq.network.p2p.NodeAddress;
|
||||||
|
|
||||||
|
@ -26,23 +28,35 @@ import bisq.common.util.Utilities;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Value
|
@Value
|
||||||
public final class PayoutTxPublishedMessage extends TradeMessage implements MailboxMessage {
|
public final class PayoutTxPublishedMessage extends TradeMessage implements MailboxMessage {
|
||||||
private final byte[] payoutTx;
|
private final byte[] payoutTx;
|
||||||
private final NodeAddress senderNodeAddress;
|
private final NodeAddress senderNodeAddress;
|
||||||
|
|
||||||
|
// Added in v1.4.0
|
||||||
|
@Nullable
|
||||||
|
private final SignedWitness signedWitness;
|
||||||
|
|
||||||
public PayoutTxPublishedMessage(String tradeId,
|
public PayoutTxPublishedMessage(String tradeId,
|
||||||
byte[] payoutTx,
|
byte[] payoutTx,
|
||||||
NodeAddress senderNodeAddress,
|
NodeAddress senderNodeAddress,
|
||||||
String uid) {
|
@Nullable SignedWitness signedWitness) {
|
||||||
this(tradeId,
|
this(tradeId,
|
||||||
payoutTx,
|
payoutTx,
|
||||||
senderNodeAddress,
|
senderNodeAddress,
|
||||||
uid,
|
signedWitness,
|
||||||
|
UUID.randomUUID().toString(),
|
||||||
Version.getP2PMessageVersion());
|
Version.getP2PMessageVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,28 +68,37 @@ public final class PayoutTxPublishedMessage extends TradeMessage implements Mail
|
||||||
private PayoutTxPublishedMessage(String tradeId,
|
private PayoutTxPublishedMessage(String tradeId,
|
||||||
byte[] payoutTx,
|
byte[] payoutTx,
|
||||||
NodeAddress senderNodeAddress,
|
NodeAddress senderNodeAddress,
|
||||||
|
@Nullable SignedWitness signedWitness,
|
||||||
String uid,
|
String uid,
|
||||||
int messageVersion) {
|
int messageVersion) {
|
||||||
super(messageVersion, tradeId, uid);
|
super(messageVersion, tradeId, uid);
|
||||||
this.payoutTx = payoutTx;
|
this.payoutTx = payoutTx;
|
||||||
this.senderNodeAddress = senderNodeAddress;
|
this.senderNodeAddress = senderNodeAddress;
|
||||||
|
this.signedWitness = signedWitness;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||||
return getNetworkEnvelopeBuilder()
|
protobuf.PayoutTxPublishedMessage.Builder builder = protobuf.PayoutTxPublishedMessage.newBuilder()
|
||||||
.setPayoutTxPublishedMessage(protobuf.PayoutTxPublishedMessage.newBuilder()
|
|
||||||
.setTradeId(tradeId)
|
.setTradeId(tradeId)
|
||||||
.setPayoutTx(ByteString.copyFrom(payoutTx))
|
.setPayoutTx(ByteString.copyFrom(payoutTx))
|
||||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||||
.setUid(uid))
|
.setUid(uid);
|
||||||
.build();
|
Optional.ofNullable(signedWitness).ifPresent(signedWitness -> builder.setSignedWitness(signedWitness.toProtoSignedWitness()));
|
||||||
|
return getNetworkEnvelopeBuilder().setPayoutTxPublishedMessage(builder).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NetworkEnvelope fromProto(protobuf.PayoutTxPublishedMessage proto, int messageVersion) {
|
public static NetworkEnvelope fromProto(protobuf.PayoutTxPublishedMessage proto, int messageVersion) {
|
||||||
|
// There is no method to check for a nullable non-primitive data type object but we know that all fields
|
||||||
|
// are empty/null, so we check for the signature to see if we got a valid signedWitness.
|
||||||
|
protobuf.SignedWitness protoSignedWitness = proto.getSignedWitness();
|
||||||
|
SignedWitness signedWitness = !protoSignedWitness.getSignature().isEmpty() ?
|
||||||
|
SignedWitness.fromProto(protoSignedWitness) :
|
||||||
|
null;
|
||||||
return new PayoutTxPublishedMessage(proto.getTradeId(),
|
return new PayoutTxPublishedMessage(proto.getTradeId(),
|
||||||
proto.getPayoutTx().toByteArray(),
|
proto.getPayoutTx().toByteArray(),
|
||||||
NodeAddress.fromProto(proto.getSenderNodeAddress()),
|
NodeAddress.fromProto(proto.getSenderNodeAddress()),
|
||||||
|
signedWitness,
|
||||||
proto.getUid(),
|
proto.getUid(),
|
||||||
messageVersion);
|
messageVersion);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +108,7 @@ public final class PayoutTxPublishedMessage extends TradeMessage implements Mail
|
||||||
return "PayoutTxPublishedMessage{" +
|
return "PayoutTxPublishedMessage{" +
|
||||||
"\n payoutTx=" + Utilities.bytesAsHexString(payoutTx) +
|
"\n payoutTx=" + Utilities.bytesAsHexString(payoutTx) +
|
||||||
",\n senderNodeAddress=" + senderNodeAddress +
|
",\n senderNodeAddress=" + senderNodeAddress +
|
||||||
",\n uid='" + uid + '\'' +
|
",\n signedWitness=" + signedWitness +
|
||||||
"\n} " + super.toString();
|
"\n} " + super.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,25 +20,19 @@ package bisq.core.trade.messages;
|
||||||
import bisq.network.p2p.MailboxMessage;
|
import bisq.network.p2p.MailboxMessage;
|
||||||
import bisq.network.p2p.NodeAddress;
|
import bisq.network.p2p.NodeAddress;
|
||||||
|
|
||||||
import bisq.common.app.Version;
|
|
||||||
|
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not used anymore since v1.4.0
|
||||||
|
* We do the re-sending of the payment sent message via the BuyerSendCounterCurrencyTransferStartedMessage task on the
|
||||||
|
* buyer side, so seller do not need to do anything interactively.
|
||||||
|
*/
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Value
|
@Value
|
||||||
public class RefreshTradeStateRequest extends TradeMessage implements MailboxMessage {
|
public class RefreshTradeStateRequest extends TradeMessage implements MailboxMessage {
|
||||||
private final NodeAddress senderNodeAddress;
|
private final NodeAddress senderNodeAddress;
|
||||||
|
|
||||||
public RefreshTradeStateRequest(String uid,
|
|
||||||
String tradeId,
|
|
||||||
NodeAddress senderNodeAddress) {
|
|
||||||
this(Version.getP2PMessageVersion(),
|
|
||||||
uid,
|
|
||||||
tradeId,
|
|
||||||
senderNodeAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// PROTO BUFFER
|
// PROTO BUFFER
|
||||||
|
@ -67,12 +61,4 @@ public class RefreshTradeStateRequest extends TradeMessage implements MailboxMes
|
||||||
proto.getTradeId(),
|
proto.getTradeId(),
|
||||||
NodeAddress.fromProto(proto.getSenderNodeAddress()));
|
NodeAddress.fromProto(proto.getSenderNodeAddress()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "RefreshTradeStateRequest{" +
|
|
||||||
"\n senderNodeAddress=" + senderNodeAddress +
|
|
||||||
"\n} " + super.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest;
|
||||||
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
|
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
|
||||||
import bisq.core.trade.messages.InputsForDepositTxRequest;
|
import bisq.core.trade.messages.InputsForDepositTxRequest;
|
||||||
import bisq.core.trade.messages.PayoutTxPublishedMessage;
|
import bisq.core.trade.messages.PayoutTxPublishedMessage;
|
||||||
import bisq.core.trade.messages.RefreshTradeStateRequest;
|
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||||
import bisq.core.trade.protocol.tasks.PublishTradeStatistics;
|
import bisq.core.trade.protocol.tasks.PublishTradeStatistics;
|
||||||
|
@ -87,6 +86,19 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
taskRunner.addTasks(BuyerSetupPayoutTxListener.class);
|
taskRunner.addTasks(BuyerSetupPayoutTxListener.class);
|
||||||
taskRunner.run();
|
taskRunner.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We might have 2 taskRunners as BuyerSetupPayoutTxListener might have been started as well
|
||||||
|
if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG ||
|
||||||
|
trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) {
|
||||||
|
// In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it
|
||||||
|
// periodically in BuyerSendCounterCurrencyTransferStartedMessage
|
||||||
|
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
|
||||||
|
() -> handleTaskRunnerSuccess("BuyerSendCounterCurrencyTransferStartedMessage"),
|
||||||
|
this::handleTaskRunnerFault);
|
||||||
|
|
||||||
|
taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class);
|
||||||
|
taskRunner.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,8 +114,6 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, peerNodeAddress);
|
handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, peerNodeAddress);
|
||||||
} else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
} else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
||||||
handle((PayoutTxPublishedMessage) tradeMessage, peerNodeAddress);
|
handle((PayoutTxPublishedMessage) tradeMessage, peerNodeAddress);
|
||||||
} else if (tradeMessage instanceof RefreshTradeStateRequest) {
|
|
||||||
handle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,23 +244,6 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Incoming message Handle missing messages
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void handle() {
|
|
||||||
// Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh
|
|
||||||
if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT &&
|
|
||||||
trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) {
|
|
||||||
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade,
|
|
||||||
() -> handleTaskRunnerSuccess("RefreshTradeStateRequest"),
|
|
||||||
this::handleTaskRunnerFault);
|
|
||||||
taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class);
|
|
||||||
taskRunner.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Message dispatcher
|
// Message dispatcher
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -268,8 +261,6 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, sender);
|
handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, sender);
|
||||||
} else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
} else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
||||||
handle((PayoutTxPublishedMessage) tradeMessage, sender);
|
handle((PayoutTxPublishedMessage) tradeMessage, sender);
|
||||||
} else if (tradeMessage instanceof RefreshTradeStateRequest) {
|
|
||||||
handle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest;
|
||||||
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
|
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
|
||||||
import bisq.core.trade.messages.InputsForDepositTxResponse;
|
import bisq.core.trade.messages.InputsForDepositTxResponse;
|
||||||
import bisq.core.trade.messages.PayoutTxPublishedMessage;
|
import bisq.core.trade.messages.PayoutTxPublishedMessage;
|
||||||
import bisq.core.trade.messages.RefreshTradeStateRequest;
|
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||||
import bisq.core.trade.protocol.tasks.PublishTradeStatistics;
|
import bisq.core.trade.protocol.tasks.PublishTradeStatistics;
|
||||||
|
@ -95,6 +94,19 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
taskRunner.addTasks(BuyerSetupPayoutTxListener.class);
|
taskRunner.addTasks(BuyerSetupPayoutTxListener.class);
|
||||||
taskRunner.run();
|
taskRunner.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We might have 2 taskRunners as BuyerSetupPayoutTxListener might have been started as well
|
||||||
|
if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG ||
|
||||||
|
trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) {
|
||||||
|
// In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it
|
||||||
|
// periodically in BuyerSendCounterCurrencyTransferStartedMessage
|
||||||
|
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
|
||||||
|
() -> handleTaskRunnerSuccess("BuyerSendCounterCurrencyTransferStartedMessage"),
|
||||||
|
this::handleTaskRunnerFault);
|
||||||
|
|
||||||
|
taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class);
|
||||||
|
taskRunner.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,8 +122,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, peerNodeAddress);
|
handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, peerNodeAddress);
|
||||||
} else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
} else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
||||||
handle((PayoutTxPublishedMessage) tradeMessage, peerNodeAddress);
|
handle((PayoutTxPublishedMessage) tradeMessage, peerNodeAddress);
|
||||||
} else if (tradeMessage instanceof RefreshTradeStateRequest) {
|
|
||||||
handle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,23 +274,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Incoming message Handle missing messages
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void handle() {
|
|
||||||
// Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh
|
|
||||||
if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT &&
|
|
||||||
trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) {
|
|
||||||
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
|
|
||||||
() -> handleTaskRunnerSuccess("RefreshTradeStateRequest"),
|
|
||||||
this::handleTaskRunnerFault);
|
|
||||||
taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class);
|
|
||||||
taskRunner.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Message dispatcher
|
// Message dispatcher
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -300,8 +293,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||||
handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, sender);
|
handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, sender);
|
||||||
} else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
} else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
||||||
handle((PayoutTxPublishedMessage) tradeMessage, sender);
|
handle((PayoutTxPublishedMessage) tradeMessage, sender);
|
||||||
} else if (tradeMessage instanceof RefreshTradeStateRequest) {
|
|
||||||
handle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage;
|
||||||
import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage;
|
import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage;
|
||||||
import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage;
|
import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage;
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
import bisq.core.trade.messages.TraderSignedWitnessMessage;
|
|
||||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessPeerPublishedDelayedPayoutTxMessage;
|
import bisq.core.trade.protocol.tasks.ProcessPeerPublishedDelayedPayoutTxMessage;
|
||||||
import bisq.core.trade.protocol.tasks.mediation.BroadcastMediatedPayoutTx;
|
import bisq.core.trade.protocol.tasks.mediation.BroadcastMediatedPayoutTx;
|
||||||
|
@ -227,15 +226,6 @@ public abstract class TradeProtocol {
|
||||||
taskRunner.run();
|
taskRunner.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Peer has sent a SignedWitness
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void handle(TraderSignedWitnessMessage tradeMessage) {
|
|
||||||
// Publish signed witness, if it is valid and ours
|
|
||||||
processModel.getAccountAgeWitnessService().publishOwnSignedWitness(tradeMessage.getSignedWitness());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Dispatcher
|
// Dispatcher
|
||||||
|
@ -248,8 +238,6 @@ public abstract class TradeProtocol {
|
||||||
handle((MediatedPayoutTxPublishedMessage) tradeMessage, sender);
|
handle((MediatedPayoutTxPublishedMessage) tradeMessage, sender);
|
||||||
} else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) {
|
} else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) {
|
||||||
handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, sender);
|
handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, sender);
|
||||||
} else if (tradeMessage instanceof TraderSignedWitnessMessage) {
|
|
||||||
handle((TraderSignedWitnessMessage) tradeMessage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,8 +285,6 @@ public abstract class TradeProtocol {
|
||||||
handle((MediatedPayoutTxPublishedMessage) tradeMessage, peerNodeAddress);
|
handle((MediatedPayoutTxPublishedMessage) tradeMessage, peerNodeAddress);
|
||||||
} else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) {
|
} else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) {
|
||||||
handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, peerNodeAddress);
|
handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, peerNodeAddress);
|
||||||
} else if (tradeMessage instanceof TraderSignedWitnessMessage) {
|
|
||||||
handle((TraderSignedWitnessMessage) tradeMessage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ public class ProcessPeerPublishedDelayedPayoutTxMessage extends TradeTask {
|
||||||
|
|
||||||
// update to the latest peer address of our peer if the message is correct
|
// update to the latest peer address of our peer if the message is correct
|
||||||
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
||||||
processModel.removeMailboxMessageAfterProcessing(trade);
|
|
||||||
|
|
||||||
// We add the tx to our wallet.
|
// We add the tx to our wallet.
|
||||||
Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx());
|
Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx());
|
||||||
|
@ -58,6 +57,8 @@ public class ProcessPeerPublishedDelayedPayoutTxMessage extends TradeTask {
|
||||||
complete();
|
complete();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
|
} finally {
|
||||||
|
processModel.removeMailboxMessageAfterProcessing(trade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Bisq.
|
||||||
|
*
|
||||||
|
* Bisq 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.
|
||||||
|
*
|
||||||
|
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package bisq.core.trade.protocol.tasks;
|
||||||
|
|
||||||
|
import bisq.core.trade.Trade;
|
||||||
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
|
|
||||||
|
import bisq.network.p2p.NodeAddress;
|
||||||
|
import bisq.network.p2p.SendMailboxMessageListener;
|
||||||
|
|
||||||
|
import bisq.common.taskrunner.TaskRunner;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public abstract class SendMailboxMessageTask extends TradeTask {
|
||||||
|
public SendMailboxMessageTask(TaskRunner<Trade> taskHandler, Trade trade) {
|
||||||
|
super(taskHandler, trade);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract TradeMessage getMessage(String id);
|
||||||
|
|
||||||
|
protected abstract void setStateSent();
|
||||||
|
|
||||||
|
protected abstract void setStateArrived();
|
||||||
|
|
||||||
|
protected abstract void setStateStoredInMailbox();
|
||||||
|
|
||||||
|
protected abstract void setStateFault();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void run() {
|
||||||
|
try {
|
||||||
|
runInterceptHook();
|
||||||
|
String id = processModel.getOfferId();
|
||||||
|
TradeMessage message = getMessage(id);
|
||||||
|
setStateSent();
|
||||||
|
NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress();
|
||||||
|
log.info("Send {} to peer {}. tradeId={}, uid={}",
|
||||||
|
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
||||||
|
|
||||||
|
processModel.getP2PService().sendEncryptedMailboxMessage(
|
||||||
|
peersNodeAddress,
|
||||||
|
processModel.getTradingPeer().getPubKeyRing(),
|
||||||
|
message,
|
||||||
|
new SendMailboxMessageListener() {
|
||||||
|
@Override
|
||||||
|
public void onArrived() {
|
||||||
|
log.info("{} arrived at peer {}. tradeId={}, uid={}",
|
||||||
|
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
||||||
|
setStateArrived();
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStoredInMailbox() {
|
||||||
|
log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}",
|
||||||
|
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
||||||
|
setStateStoredInMailbox();
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFault(String errorMessage) {
|
||||||
|
log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
|
||||||
|
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
|
||||||
|
setStateFault();
|
||||||
|
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||||
|
failed(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
failed(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Bisq.
|
|
||||||
*
|
|
||||||
* Bisq 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.
|
|
||||||
*
|
|
||||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package bisq.core.trade.protocol.tasks;
|
|
||||||
|
|
||||||
import bisq.core.trade.Trade;
|
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
|
||||||
|
|
||||||
import bisq.network.p2p.NodeAddress;
|
|
||||||
import bisq.network.p2p.SendMailboxMessageListener;
|
|
||||||
|
|
||||||
import bisq.common.taskrunner.TaskRunner;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public abstract class SendPayoutTxPublishedMessage extends TradeTask {
|
|
||||||
public SendPayoutTxPublishedMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
|
||||||
super(taskHandler, trade);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract TradeMessage getMessage(String id);
|
|
||||||
|
|
||||||
protected abstract void setStateSent();
|
|
||||||
|
|
||||||
protected abstract void setStateArrived();
|
|
||||||
|
|
||||||
protected abstract void setStateStoredInMailbox();
|
|
||||||
|
|
||||||
protected abstract void setStateFault();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void run() {
|
|
||||||
try {
|
|
||||||
runInterceptHook();
|
|
||||||
if (trade.getPayoutTx() != null) {
|
|
||||||
String id = processModel.getOfferId();
|
|
||||||
TradeMessage message = getMessage(id);
|
|
||||||
setStateSent();
|
|
||||||
NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress();
|
|
||||||
log.info("Send {} to peer {}. tradeId={}, uid={}",
|
|
||||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
|
||||||
|
|
||||||
processModel.getP2PService().sendEncryptedMailboxMessage(
|
|
||||||
peersNodeAddress,
|
|
||||||
processModel.getTradingPeer().getPubKeyRing(),
|
|
||||||
message,
|
|
||||||
new SendMailboxMessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onArrived() {
|
|
||||||
log.info("{} arrived at peer {}. tradeId={}, uid={}",
|
|
||||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
|
||||||
setStateArrived();
|
|
||||||
complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStoredInMailbox() {
|
|
||||||
log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}",
|
|
||||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
|
||||||
setStateStoredInMailbox();
|
|
||||||
complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFault(String errorMessage) {
|
|
||||||
log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
|
|
||||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
|
|
||||||
setStateFault();
|
|
||||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
|
||||||
failed(errorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
log.error("trade.getPayoutTx() = " + trade.getPayoutTx());
|
|
||||||
failed("PayoutTx is null");
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
failed(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -65,8 +65,6 @@ public class BuyerProcessDepositTxAndDelayedPayoutTxMessage extends TradeTask {
|
||||||
|
|
||||||
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
||||||
|
|
||||||
processModel.removeMailboxMessageAfterProcessing(trade);
|
|
||||||
|
|
||||||
// If we got already the confirmation we don't want to apply an earlier state
|
// 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()) {
|
if (trade.getState().ordinal() < Trade.State.BUYER_SAW_DEPOSIT_TX_IN_NETWORK.ordinal()) {
|
||||||
trade.setState(Trade.State.BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG);
|
trade.setState(Trade.State.BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG);
|
||||||
|
@ -78,6 +76,8 @@ public class BuyerProcessDepositTxAndDelayedPayoutTxMessage extends TradeTask {
|
||||||
complete();
|
complete();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
|
} finally {
|
||||||
|
processModel.removeMailboxMessageAfterProcessing(trade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package bisq.core.trade.protocol.tasks.buyer;
|
package bisq.core.trade.protocol.tasks.buyer;
|
||||||
|
|
||||||
|
import bisq.core.account.sign.SignedWitness;
|
||||||
import bisq.core.btc.model.AddressEntry;
|
import bisq.core.btc.model.AddressEntry;
|
||||||
import bisq.core.btc.wallet.BtcWalletService;
|
import bisq.core.btc.wallet.BtcWalletService;
|
||||||
import bisq.core.btc.wallet.WalletService;
|
import bisq.core.btc.wallet.WalletService;
|
||||||
|
@ -63,10 +64,20 @@ public class BuyerProcessPayoutTxPublishedMessage extends TradeTask {
|
||||||
} else {
|
} else {
|
||||||
log.info("We got the payout tx already set from BuyerSetupPayoutTxListener and do nothing here. trade ID={}", trade.getId());
|
log.info("We got the payout tx already set from BuyerSetupPayoutTxListener and do nothing here. trade ID={}", trade.getId());
|
||||||
}
|
}
|
||||||
processModel.removeMailboxMessageAfterProcessing(trade);
|
|
||||||
|
SignedWitness signedWitness = message.getSignedWitness();
|
||||||
|
if (signedWitness != null) {
|
||||||
|
// We received the signedWitness from the seller and publish the data to the network.
|
||||||
|
// The signer has published it as well but we prefer to re-do it on our side as well to achieve higher
|
||||||
|
// resilience.
|
||||||
|
processModel.getAccountAgeWitnessService().publishOwnSignedWitness(signedWitness);
|
||||||
|
}
|
||||||
|
|
||||||
complete();
|
complete();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
|
} finally {
|
||||||
|
processModel.removeMailboxMessageAfterProcessing(trade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,81 +18,122 @@
|
||||||
package bisq.core.trade.protocol.tasks.buyer;
|
package bisq.core.trade.protocol.tasks.buyer;
|
||||||
|
|
||||||
import bisq.core.btc.model.AddressEntry;
|
import bisq.core.btc.model.AddressEntry;
|
||||||
import bisq.core.btc.wallet.BtcWalletService;
|
import bisq.core.network.MessageState;
|
||||||
|
import bisq.core.payment.payload.PaymentMethod;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage;
|
import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage;
|
||||||
import bisq.core.trade.protocol.tasks.TradeTask;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
|
import bisq.core.trade.protocol.tasks.SendMailboxMessageTask;
|
||||||
import bisq.network.p2p.NodeAddress;
|
|
||||||
import bisq.network.p2p.SendMailboxMessageListener;
|
|
||||||
|
|
||||||
|
import bisq.common.Timer;
|
||||||
|
import bisq.common.UserThread;
|
||||||
import bisq.common.taskrunner.TaskRunner;
|
import bisq.common.taskrunner.TaskRunner;
|
||||||
|
|
||||||
import java.util.UUID;
|
import javafx.beans.value.ChangeListener;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class BuyerSendCounterCurrencyTransferStartedMessage extends TradeTask {
|
public class BuyerSendCounterCurrencyTransferStartedMessage extends SendMailboxMessageTask {
|
||||||
|
private static final long MAX_REFRESH_INTERVAL = TimeUnit.HOURS.toMillis(4);
|
||||||
|
|
||||||
|
private ChangeListener<MessageState> listener;
|
||||||
|
private Timer timer;
|
||||||
|
private CounterCurrencyTransferStartedMessage counterCurrencyTransferStartedMessage;
|
||||||
|
|
||||||
public BuyerSendCounterCurrencyTransferStartedMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
public BuyerSendCounterCurrencyTransferStartedMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
||||||
super(taskHandler, trade);
|
super(taskHandler, trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TradeMessage getMessage(String tradeId) {
|
||||||
|
if (counterCurrencyTransferStartedMessage == null) {
|
||||||
|
AddressEntry payoutAddressEntry = processModel.getBtcWalletService().getOrCreateAddressEntry(tradeId,
|
||||||
|
AddressEntry.Context.TRADE_PAYOUT);
|
||||||
|
|
||||||
|
// 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 = tradeId + processModel.getMyNodeAddress().getFullAddress();
|
||||||
|
counterCurrencyTransferStartedMessage = new CounterCurrencyTransferStartedMessage(
|
||||||
|
tradeId,
|
||||||
|
payoutAddressEntry.getAddressString(),
|
||||||
|
processModel.getMyNodeAddress(),
|
||||||
|
processModel.getPayoutTxSignature(),
|
||||||
|
trade.getCounterCurrencyTxId(),
|
||||||
|
trade.getCounterCurrencyExtraData(),
|
||||||
|
deterministicId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return counterCurrencyTransferStartedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setStateSent() {
|
||||||
|
trade.setState(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setStateArrived() {
|
||||||
|
trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG);
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setStateStoredInMailbox() {
|
||||||
|
trade.setState(Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG);
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setStateFault() {
|
||||||
|
trade.setState(Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG);
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() {
|
protected void run() {
|
||||||
try {
|
try {
|
||||||
runInterceptHook();
|
runInterceptHook();
|
||||||
|
|
||||||
BtcWalletService walletService = processModel.getBtcWalletService();
|
super.run();
|
||||||
final String id = processModel.getOfferId();
|
|
||||||
AddressEntry payoutAddressEntry = walletService.getOrCreateAddressEntry(id,
|
|
||||||
AddressEntry.Context.TRADE_PAYOUT);
|
|
||||||
final CounterCurrencyTransferStartedMessage message = new CounterCurrencyTransferStartedMessage(
|
|
||||||
id,
|
|
||||||
payoutAddressEntry.getAddressString(),
|
|
||||||
processModel.getMyNodeAddress(),
|
|
||||||
processModel.getPayoutTxSignature(),
|
|
||||||
trade.getCounterCurrencyTxId(),
|
|
||||||
trade.getCounterCurrencyExtraData(),
|
|
||||||
UUID.randomUUID().toString()
|
|
||||||
);
|
|
||||||
NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress();
|
|
||||||
log.info("Send {} to peer {}. tradeId={}, uid={}",
|
|
||||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
|
||||||
trade.setState(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG);
|
|
||||||
processModel.getP2PService().sendEncryptedMailboxMessage(
|
|
||||||
peersNodeAddress,
|
|
||||||
processModel.getTradingPeer().getPubKeyRing(),
|
|
||||||
message,
|
|
||||||
new SendMailboxMessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onArrived() {
|
|
||||||
log.info("{} arrived at peer {}. tradeId={}, uid={}",
|
|
||||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
|
||||||
trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG);
|
|
||||||
complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStoredInMailbox() {
|
|
||||||
log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}",
|
|
||||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
|
||||||
trade.setState(Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG);
|
|
||||||
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.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG);
|
|
||||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
|
||||||
failed(errorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void stop() {
|
||||||
|
if (timer != null) {
|
||||||
|
timer.stop();
|
||||||
|
processModel.getPaymentStartedMessageStateProperty().removeListener(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The listeners ensure we don't get GCed even we have completed the task.
|
||||||
|
private void start() {
|
||||||
|
if (timer != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaymentMethod paymentMethod = checkNotNull(trade.getOffer()).getPaymentMethod();
|
||||||
|
// For instant trades with 1 hour we want a short interval, otherwise a few hours should be ok.
|
||||||
|
long interval = Math.min(paymentMethod.getMaxTradePeriod() / 5, MAX_REFRESH_INTERVAL);
|
||||||
|
timer = UserThread.runPeriodically(this::run, interval, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
listener = (observable, oldValue, newValue) -> {
|
||||||
|
// Once we receive an ACK from our msg we know the peer has received the msg and we stop.
|
||||||
|
if (newValue == MessageState.ACKNOWLEDGED) {
|
||||||
|
// We treat a ACK like BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG
|
||||||
|
trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG);
|
||||||
|
// Ensure listener construction is completed before remove call
|
||||||
|
UserThread.execute(this::stop);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
processModel.getPaymentStartedMessageStateProperty().addListener(listener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,13 +48,14 @@ public class ProcessMediatedPayoutSignatureMessage extends TradeTask {
|
||||||
|
|
||||||
// update to the latest peer address of our peer if the message is correct
|
// update to the latest peer address of our peer if the message is correct
|
||||||
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress());
|
||||||
processModel.removeMailboxMessageAfterProcessing(trade);
|
|
||||||
|
|
||||||
trade.setMediationResultState(MediationResultState.RECEIVED_SIG_MSG);
|
trade.setMediationResultState(MediationResultState.RECEIVED_SIG_MSG);
|
||||||
|
|
||||||
complete();
|
complete();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
|
} finally {
|
||||||
|
processModel.removeMailboxMessageAfterProcessing(trade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,10 +74,11 @@ public class ProcessMediatedPayoutTxPublishedMessage extends TradeTask {
|
||||||
} else {
|
} else {
|
||||||
log.info("We got the payout tx already set from BuyerSetupPayoutTxListener and do nothing here. trade ID={}", trade.getId());
|
log.info("We got the payout tx already set from BuyerSetupPayoutTxListener and do nothing here. trade ID={}", trade.getId());
|
||||||
}
|
}
|
||||||
processModel.removeMailboxMessageAfterProcessing(trade);
|
|
||||||
complete();
|
complete();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
|
} finally {
|
||||||
|
processModel.removeMailboxMessageAfterProcessing(trade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import bisq.core.support.dispute.mediation.MediationResultState;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage;
|
import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage;
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
import bisq.core.trade.protocol.tasks.SendPayoutTxPublishedMessage;
|
import bisq.core.trade.protocol.tasks.SendMailboxMessageTask;
|
||||||
|
|
||||||
import bisq.common.taskrunner.TaskRunner;
|
import bisq.common.taskrunner.TaskRunner;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SendMediatedPayoutTxPublishedMessage extends SendPayoutTxPublishedMessage {
|
public class SendMediatedPayoutTxPublishedMessage extends SendMailboxMessageTask {
|
||||||
public SendMediatedPayoutTxPublishedMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
public SendMediatedPayoutTxPublishedMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
||||||
super(taskHandler, trade);
|
super(taskHandler, trade);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,12 @@ public class SendMediatedPayoutTxPublishedMessage extends SendPayoutTxPublishedM
|
||||||
try {
|
try {
|
||||||
runInterceptHook();
|
runInterceptHook();
|
||||||
|
|
||||||
|
if (trade.getPayoutTx() == null) {
|
||||||
|
log.error("PayoutTx is null");
|
||||||
|
failed("PayoutTx is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
super.run();
|
super.run();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
|
|
|
@ -59,13 +59,13 @@ public class SellerProcessCounterCurrencyTransferStartedMessage extends TradeTas
|
||||||
trade.setCounterCurrencyExtraData(counterCurrencyExtraData);
|
trade.setCounterCurrencyExtraData(counterCurrencyExtraData);
|
||||||
}
|
}
|
||||||
|
|
||||||
processModel.removeMailboxMessageAfterProcessing(trade);
|
|
||||||
|
|
||||||
trade.setState(Trade.State.SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG);
|
trade.setState(Trade.State.SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG);
|
||||||
|
|
||||||
complete();
|
complete();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
|
} finally {
|
||||||
|
processModel.removeMailboxMessageAfterProcessing(trade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,23 +17,27 @@
|
||||||
|
|
||||||
package bisq.core.trade.protocol.tasks.seller;
|
package bisq.core.trade.protocol.tasks.seller;
|
||||||
|
|
||||||
|
import bisq.core.account.sign.SignedWitness;
|
||||||
|
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.messages.PayoutTxPublishedMessage;
|
import bisq.core.trade.messages.PayoutTxPublishedMessage;
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
import bisq.core.trade.protocol.tasks.SendPayoutTxPublishedMessage;
|
import bisq.core.trade.protocol.tasks.SendMailboxMessageTask;
|
||||||
|
|
||||||
import bisq.common.taskrunner.TaskRunner;
|
import bisq.common.taskrunner.TaskRunner;
|
||||||
|
|
||||||
import org.bitcoinj.core.Transaction;
|
import org.bitcoinj.core.Transaction;
|
||||||
|
|
||||||
import java.util.UUID;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SellerSendPayoutTxPublishedMessage extends SendPayoutTxPublishedMessage {
|
public class SellerSendPayoutTxPublishedMessage extends SendMailboxMessageTask {
|
||||||
|
SignedWitness signedWitness = null;
|
||||||
|
|
||||||
public SellerSendPayoutTxPublishedMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
public SellerSendPayoutTxPublishedMessage(TaskRunner<Trade> taskHandler, Trade trade) {
|
||||||
super(taskHandler, trade);
|
super(taskHandler, trade);
|
||||||
}
|
}
|
||||||
|
@ -41,32 +45,47 @@ public class SellerSendPayoutTxPublishedMessage extends SendPayoutTxPublishedMes
|
||||||
@Override
|
@Override
|
||||||
protected TradeMessage getMessage(String id) {
|
protected TradeMessage getMessage(String id) {
|
||||||
Transaction payoutTx = checkNotNull(trade.getPayoutTx(), "trade.getPayoutTx() must not be null");
|
Transaction payoutTx = checkNotNull(trade.getPayoutTx(), "trade.getPayoutTx() must not be null");
|
||||||
|
|
||||||
|
AccountAgeWitnessService accountAgeWitnessService = processModel.getAccountAgeWitnessService();
|
||||||
|
if (accountAgeWitnessService.isSignWitnessTrade(trade)) {
|
||||||
|
// Broadcast is done in accountAgeWitness domain.
|
||||||
|
accountAgeWitnessService.traderSignAndPublishPeersAccountAgeWitness(trade).ifPresent(witness -> signedWitness = witness);
|
||||||
|
}
|
||||||
|
|
||||||
return new PayoutTxPublishedMessage(
|
return new PayoutTxPublishedMessage(
|
||||||
id,
|
id,
|
||||||
payoutTx.bitcoinSerialize(),
|
payoutTx.bitcoinSerialize(),
|
||||||
processModel.getMyNodeAddress(),
|
processModel.getMyNodeAddress(),
|
||||||
UUID.randomUUID().toString()
|
signedWitness
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateSent() {
|
protected void setStateSent() {
|
||||||
trade.setState(Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG);
|
trade.setState(Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG);
|
||||||
|
log.info("Sent PayoutTxPublishedMessage: tradeId={} at peer {} SignedWitness {}",
|
||||||
|
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateArrived() {
|
protected void setStateArrived() {
|
||||||
trade.setState(Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG);
|
trade.setState(Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG);
|
||||||
|
log.info("PayoutTxPublishedMessage arrived: tradeId={} at peer {} SignedWitness {}",
|
||||||
|
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateStoredInMailbox() {
|
protected void setStateStoredInMailbox() {
|
||||||
trade.setState(Trade.State.SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG);
|
trade.setState(Trade.State.SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG);
|
||||||
|
log.info("PayoutTxPublishedMessage storedInMailbox: tradeId={} at peer {} SignedWitness {}",
|
||||||
|
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setStateFault() {
|
protected void setStateFault() {
|
||||||
trade.setState(Trade.State.SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG);
|
trade.setState(Trade.State.SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG);
|
||||||
|
log.error("PayoutTxPublishedMessage failed: tradeId={} at peer {} SignedWitness {}",
|
||||||
|
trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -74,6 +93,12 @@ public class SellerSendPayoutTxPublishedMessage extends SendPayoutTxPublishedMes
|
||||||
try {
|
try {
|
||||||
runInterceptHook();
|
runInterceptHook();
|
||||||
|
|
||||||
|
if (trade.getPayoutTx() == null) {
|
||||||
|
log.error("PayoutTx is null");
|
||||||
|
failed("PayoutTx is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
super.run();
|
super.run();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
failed(t);
|
failed(t);
|
||||||
|
|
|
@ -354,7 +354,7 @@ public class SignedWitnessServiceTest {
|
||||||
when(keyRing.getSignatureKeyPair()).thenReturn(signerKeyPair);
|
when(keyRing.getSignatureKeyPair()).thenReturn(signerKeyPair);
|
||||||
|
|
||||||
AccountAgeWitness accountAgeWitness = new AccountAgeWitness(account1DataHash, accountCreationTime);
|
AccountAgeWitness accountAgeWitness = new AccountAgeWitness(account1DataHash, accountCreationTime);
|
||||||
signedWitnessService.signAccountAgeWitness(Coin.ZERO, accountAgeWitness, peerKeyPair.getPublic());
|
signedWitnessService.signAndPublishAccountAgeWitness(Coin.ZERO, accountAgeWitness, peerKeyPair.getPublic());
|
||||||
|
|
||||||
verify(p2pService, never()).addPersistableNetworkPayload(any(PersistableNetworkPayload.class), anyBoolean());
|
verify(p2pService, never()).addPersistableNetworkPayload(any(PersistableNetworkPayload.class), anyBoolean());
|
||||||
}
|
}
|
||||||
|
@ -370,7 +370,7 @@ public class SignedWitnessServiceTest {
|
||||||
|
|
||||||
|
|
||||||
AccountAgeWitness accountAgeWitness = new AccountAgeWitness(account1DataHash, accountCreationTime);
|
AccountAgeWitness accountAgeWitness = new AccountAgeWitness(account1DataHash, accountCreationTime);
|
||||||
signedWitnessService.signAccountAgeWitness(SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, peerKeyPair.getPublic());
|
signedWitnessService.signAndPublishAccountAgeWitness(SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, peerKeyPair.getPublic());
|
||||||
|
|
||||||
verify(p2pService, times(1)).addPersistableNetworkPayload(any(PersistableNetworkPayload.class), anyBoolean());
|
verify(p2pService, times(1)).addPersistableNetworkPayload(any(PersistableNetworkPayload.class), anyBoolean());
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,7 +301,7 @@ public class AccountAgeWitnessServiceTest {
|
||||||
signAccountAgeWitness(aew2, pubKeyRing2.getSignaturePubKey(), aew2.getDate(), user1KeyRing);
|
signAccountAgeWitness(aew2, pubKeyRing2.getSignaturePubKey(), aew2.getDate(), user1KeyRing);
|
||||||
// user2 signs user3
|
// user2 signs user3
|
||||||
signAccountAgeWitness(aew3, pubKeyRing3.getSignaturePubKey(), aew3.getDate(), user2KeyRing);
|
signAccountAgeWitness(aew3, pubKeyRing3.getSignaturePubKey(), aew3.getDate(), user2KeyRing);
|
||||||
signedWitnessService.signAccountAgeWitness(SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING, aew2,
|
signedWitnessService.signAndPublishAccountAgeWitness(SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING, aew2,
|
||||||
pubKeyRing2.getSignaturePubKey());
|
pubKeyRing2.getSignaturePubKey());
|
||||||
assertTrue(service.accountIsSigner(aew1));
|
assertTrue(service.accountIsSigner(aew1));
|
||||||
assertTrue(service.accountIsSigner(aew2));
|
assertTrue(service.accountIsSigner(aew2));
|
||||||
|
|
|
@ -130,7 +130,7 @@ class FiatAccountsDataModel extends ActivatableDataModel {
|
||||||
user.addPaymentAccount(paymentAccount);
|
user.addPaymentAccount(paymentAccount);
|
||||||
|
|
||||||
accountAgeWitnessService.publishMyAccountAgeWitness(paymentAccount.getPaymentAccountPayload());
|
accountAgeWitnessService.publishMyAccountAgeWitness(paymentAccount.getPaymentAccountPayload());
|
||||||
accountAgeWitnessService.signSameNameAccounts();
|
accountAgeWitnessService.signAndPublishSameNameAccounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onDeleteAccount(PaymentAccount paymentAccount) {
|
public boolean onDeleteAccount(PaymentAccount paymentAccount) {
|
||||||
|
|
|
@ -50,13 +50,10 @@ import bisq.core.trade.BuyerTrade;
|
||||||
import bisq.core.trade.SellerTrade;
|
import bisq.core.trade.SellerTrade;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.TradeManager;
|
import bisq.core.trade.TradeManager;
|
||||||
import bisq.core.trade.messages.RefreshTradeStateRequest;
|
|
||||||
import bisq.core.user.Preferences;
|
import bisq.core.user.Preferences;
|
||||||
import bisq.core.util.FormattingUtils;
|
import bisq.core.util.FormattingUtils;
|
||||||
|
|
||||||
import bisq.network.p2p.NodeAddress;
|
|
||||||
import bisq.network.p2p.P2PService;
|
import bisq.network.p2p.P2PService;
|
||||||
import bisq.network.p2p.SendMailboxMessageListener;
|
|
||||||
|
|
||||||
import bisq.common.crypto.PubKeyRing;
|
import bisq.common.crypto.PubKeyRing;
|
||||||
import bisq.common.handlers.ErrorMessageHandler;
|
import bisq.common.handlers.ErrorMessageHandler;
|
||||||
|
@ -81,7 +78,6 @@ import javafx.collections.ObservableList;
|
||||||
|
|
||||||
import org.bouncycastle.crypto.params.KeyParameter;
|
import org.bouncycastle.crypto.params.KeyParameter;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
@ -237,43 +233,6 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||||
tradeManager.addTradeToFailedTrades(getTrade());
|
tradeManager.addTradeToFailedTrades(getTrade());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask counterparty to resend last action (in case message was lost)
|
|
||||||
public void refreshTradeState() {
|
|
||||||
Trade trade = getTrade();
|
|
||||||
if (trade == null || !trade.allowedRefresh()) return;
|
|
||||||
|
|
||||||
trade.logRefresh();
|
|
||||||
NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress();
|
|
||||||
|
|
||||||
RefreshTradeStateRequest refreshReq = new RefreshTradeStateRequest(UUID.randomUUID().toString(),
|
|
||||||
trade.getId(),
|
|
||||||
tradingPeerNodeAddress);
|
|
||||||
p2PService.sendEncryptedMailboxMessage(
|
|
||||||
tradingPeerNodeAddress,
|
|
||||||
trade.getProcessModel().getTradingPeer().getPubKeyRing(),
|
|
||||||
refreshReq,
|
|
||||||
new SendMailboxMessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onArrived() {
|
|
||||||
log.info("SendMailboxMessageListener onArrived tradeId={} at peer {}",
|
|
||||||
trade.getId(), tradingPeerNodeAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStoredInMailbox() {
|
|
||||||
log.info("SendMailboxMessageListener onStoredInMailbox tradeId={} at peer {}",
|
|
||||||
trade.getId(), tradingPeerNodeAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFault(String errorMessage) {
|
|
||||||
log.error("SendMailboxMessageListener onFault tradeId={} at peer {}",
|
|
||||||
trade.getId(), tradingPeerNodeAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
tradeManager.persistTrades();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Getters
|
// Getters
|
||||||
|
|
|
@ -216,8 +216,6 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||||
new Popup().warning(Res.get("portfolio.pending.removeFailedTrade"))
|
new Popup().warning(Res.get("portfolio.pending.removeFailedTrade"))
|
||||||
.onAction(model.dataModel::onMoveToFailedTrades)
|
.onAction(model.dataModel::onMoveToFailedTrades)
|
||||||
.show();
|
.show();
|
||||||
} else if (Utilities.isAltOrCtrlPressed(KeyCode.R, keyEvent)) {
|
|
||||||
model.dataModel.refreshTradeState();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,27 +24,12 @@ import bisq.desktop.util.Layout;
|
||||||
|
|
||||||
import bisq.core.locale.Res;
|
import bisq.core.locale.Res;
|
||||||
import bisq.core.payment.payload.F2FAccountPayload;
|
import bisq.core.payment.payload.F2FAccountPayload;
|
||||||
import bisq.core.trade.Trade;
|
|
||||||
|
|
||||||
import bisq.common.Timer;
|
|
||||||
import bisq.common.UserThread;
|
|
||||||
|
|
||||||
import javafx.scene.control.Button;
|
|
||||||
import javafx.scene.layout.GridPane;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static bisq.desktop.util.FormBuilder.addButtonAfterGroup;
|
|
||||||
import static bisq.desktop.util.FormBuilder.addMultilineLabel;
|
|
||||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
public class SellerStep2View extends TradeStepView {
|
public class SellerStep2View extends TradeStepView {
|
||||||
|
|
||||||
private GridPane refreshButtonPane;
|
|
||||||
private Timer timer;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructor, Initialisation
|
// Constructor, Initialisation
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -65,61 +50,16 @@ public class SellerStep2View extends TradeStepView {
|
||||||
gridRow = F2FForm.addFormForBuyer(gridPane, --gridRow, model.dataModel.getSellersPaymentAccountPayload(),
|
gridRow = F2FForm.addFormForBuyer(gridPane, --gridRow, model.dataModel.getSellersPaymentAccountPayload(),
|
||||||
model.dataModel.getTrade().getOffer(), Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE);
|
model.dataModel.getTrade().getOffer(), Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
addRefreshBlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRefreshBlock() {
|
|
||||||
refreshButtonPane = new GridPane();
|
|
||||||
addTitledGroupBg(refreshButtonPane, 0, 1,
|
|
||||||
Res.get("portfolio.pending.step2_seller.refresh"), Layout.COMPACT_GROUP_DISTANCE);
|
|
||||||
addMultilineLabel(refreshButtonPane, 1, Res.get("portfolio.pending.step2_seller.refreshInfo"),
|
|
||||||
Layout.COMPACT_FIRST_ROW_DISTANCE);
|
|
||||||
Button refreshButton = addButtonAfterGroup(refreshButtonPane, 2, Res.get("portfolio.pending.step2_seller.refresh"));
|
|
||||||
refreshButton.setOnAction(event -> onRefreshButton());
|
|
||||||
|
|
||||||
GridPane.setRowIndex(refreshButtonPane, ++gridRow);
|
|
||||||
GridPane.setColumnIndex(refreshButtonPane, 0);
|
|
||||||
GridPane.setColumnSpan(refreshButtonPane, 2);
|
|
||||||
gridPane.getChildren().add(refreshButtonPane);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activate() {
|
public void activate() {
|
||||||
super.activate();
|
super.activate();
|
||||||
activateRefreshButton();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deactivate() {
|
public void deactivate() {
|
||||||
super.deactivate();
|
super.deactivate();
|
||||||
deActivateRefreshButtonTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void activateRefreshButton() {
|
|
||||||
checkNotNull(model.dataModel.getTrade(), "No trade found");
|
|
||||||
|
|
||||||
Trade trade = model.dataModel.getTrade();
|
|
||||||
var timeToNextRefresh =
|
|
||||||
trade.getLastRefreshRequestDate() + trade.getRefreshInterval() - new Date().getTime();
|
|
||||||
if (timeToNextRefresh <= 0) {
|
|
||||||
refreshButtonPane.setVisible(true);
|
|
||||||
} else {
|
|
||||||
refreshButtonPane.setVisible(false);
|
|
||||||
timer = UserThread.runAfter(this::activateRefreshButton, timeToNextRefresh, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deActivateRefreshButtonTimer() {
|
|
||||||
if (timer != null) {
|
|
||||||
timer.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onRefreshButton() {
|
|
||||||
model.dataModel.refreshTradeState();
|
|
||||||
activateRefreshButton();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ message NetworkEnvelope {
|
||||||
DepositTxAndDelayedPayoutTxMessage deposit_tx_and_delayed_payout_tx_message = 48;
|
DepositTxAndDelayedPayoutTxMessage deposit_tx_and_delayed_payout_tx_message = 48;
|
||||||
PeerPublishedDelayedPayoutTxMessage peer_published_delayed_payout_tx_message = 49;
|
PeerPublishedDelayedPayoutTxMessage peer_published_delayed_payout_tx_message = 49;
|
||||||
|
|
||||||
RefreshTradeStateRequest refresh_trade_state_request = 50;
|
RefreshTradeStateRequest refresh_trade_state_request = 50 [deprecated = true];
|
||||||
TraderSignedWitnessMessage trader_signed_witness_message = 51;
|
TraderSignedWitnessMessage trader_signed_witness_message = 51;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,6 +309,7 @@ message PayoutTxPublishedMessage {
|
||||||
bytes payout_tx = 2;
|
bytes payout_tx = 2;
|
||||||
NodeAddress sender_node_address = 3;
|
NodeAddress sender_node_address = 3;
|
||||||
string uid = 4;
|
string uid = 4;
|
||||||
|
SignedWitness signed_witness = 5; // Added in v1.4.0
|
||||||
}
|
}
|
||||||
|
|
||||||
message MediatedPayoutTxPublishedMessage {
|
message MediatedPayoutTxPublishedMessage {
|
||||||
|
@ -325,17 +326,19 @@ message MediatedPayoutTxSignatureMessage {
|
||||||
NodeAddress sender_node_address = 4;
|
NodeAddress sender_node_address = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated since 1.4.0
|
||||||
message RefreshTradeStateRequest {
|
message RefreshTradeStateRequest {
|
||||||
string uid = 1;
|
string uid = 1 [deprecated = true];
|
||||||
string trade_id = 2;
|
string trade_id = 2 [deprecated = true];
|
||||||
NodeAddress sender_node_address = 3;
|
NodeAddress sender_node_address = 3 [deprecated = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated since 1.4.0
|
||||||
message TraderSignedWitnessMessage {
|
message TraderSignedWitnessMessage {
|
||||||
string uid = 1;
|
string uid = 1 [deprecated = true];
|
||||||
string trade_id = 2;
|
string trade_id = 2 [deprecated = true];
|
||||||
NodeAddress sender_node_address = 3;
|
NodeAddress sender_node_address = 3 [deprecated = true];
|
||||||
SignedWitness signed_witness = 4;
|
SignedWitness signed_witness = 4 [deprecated = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
// dispute
|
// dispute
|
||||||
|
|
Loading…
Add table
Reference in a new issue