mirror of
https://github.com/boldsuck/haveno.git
synced 2024-12-23 04:29:22 +00:00
add date and key images to SignedOffer
arbitrator retains failed trades after reserve tx received legacy ui shows trade details including reserve tx, with or w/o contract fix npe searching arbitrator tickets due to null payment accounts synchronize offer book list items fix npe before key image poller initialized
This commit is contained in:
parent
882f1c070a
commit
a0235c8ebd
8 changed files with 194 additions and 153 deletions
|
@ -100,6 +100,7 @@ public class OfferBookService {
|
||||||
connectionsService.addListener(new MoneroConnectionManagerListener() {
|
connectionsService.addListener(new MoneroConnectionManagerListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onConnectionChanged(MoneroRpcConnection connection) {
|
public void onConnectionChanged(MoneroRpcConnection connection) {
|
||||||
|
if (keyImagePoller == null) return;
|
||||||
keyImagePoller.setDaemon(connectionsService.getDaemon());
|
keyImagePoller.setDaemon(connectionsService.getDaemon());
|
||||||
keyImagePoller.setRefreshPeriodMs(getKeyImageRefreshPeriodMs());
|
keyImagePoller.setRefreshPeriodMs(getKeyImageRefreshPeriodMs());
|
||||||
}
|
}
|
||||||
|
|
|
@ -925,7 +925,13 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
signedOfferPayload.setArbitratorSignature(signature);
|
signedOfferPayload.setArbitratorSignature(signature);
|
||||||
|
|
||||||
// create record of signed offer
|
// create record of signed offer
|
||||||
SignedOffer signedOffer = new SignedOffer(signedOfferPayload.getId(), request.getReserveTxHash(), request.getReserveTxHex(), signature); // TODO (woodser): no need for signature to be part of SignedOffer?
|
SignedOffer signedOffer = new SignedOffer(
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
signedOfferPayload.getId(),
|
||||||
|
request.getReserveTxHash(),
|
||||||
|
request.getReserveTxHex(),
|
||||||
|
request.getReserveTxKeyImages(),
|
||||||
|
signature); // TODO (woodser): no need for signature to be part of SignedOffer?
|
||||||
addSignedOffer(signedOffer);
|
addSignedOffer(signedOffer);
|
||||||
requestPersistence();
|
requestPersistence();
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
package bisq.core.offer;
|
package bisq.core.offer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import bisq.common.proto.persistable.PersistablePayload;
|
import bisq.common.proto.persistable.PersistablePayload;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
@ -26,6 +28,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public final class SignedOffer implements PersistablePayload {
|
public final class SignedOffer implements PersistablePayload {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final long timeStamp;
|
||||||
@Getter
|
@Getter
|
||||||
private final String offerId;
|
private final String offerId;
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -33,12 +37,16 @@ public final class SignedOffer implements PersistablePayload {
|
||||||
@Getter
|
@Getter
|
||||||
private final String reserveTxHex;
|
private final String reserveTxHex;
|
||||||
@Getter
|
@Getter
|
||||||
|
private final List<String> reserveTxKeyImages;
|
||||||
|
@Getter
|
||||||
private final String arbitratorSignature;
|
private final String arbitratorSignature;
|
||||||
|
|
||||||
public SignedOffer(String offerId, String reserveTxHash, String reserveTxHex, String arbitratorSignature) {
|
public SignedOffer(long timeStamp, String offerId, String reserveTxHash, String reserveTxHex, List<String> reserveTxKeyImages, String arbitratorSignature) {
|
||||||
|
this.timeStamp = timeStamp;
|
||||||
this.offerId = offerId;
|
this.offerId = offerId;
|
||||||
this.reserveTxHash = reserveTxHash;
|
this.reserveTxHash = reserveTxHash;
|
||||||
this.reserveTxHex = reserveTxHex;
|
this.reserveTxHex = reserveTxHex;
|
||||||
|
this.reserveTxKeyImages = reserveTxKeyImages;
|
||||||
this.arbitratorSignature = arbitratorSignature;
|
this.arbitratorSignature = arbitratorSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,16 +57,17 @@ public final class SignedOffer implements PersistablePayload {
|
||||||
@Override
|
@Override
|
||||||
public protobuf.SignedOffer toProtoMessage() {
|
public protobuf.SignedOffer toProtoMessage() {
|
||||||
protobuf.SignedOffer.Builder builder = protobuf.SignedOffer.newBuilder()
|
protobuf.SignedOffer.Builder builder = protobuf.SignedOffer.newBuilder()
|
||||||
|
.setTimeStamp(timeStamp)
|
||||||
.setOfferId(offerId)
|
.setOfferId(offerId)
|
||||||
.setReserveTxHash(reserveTxHash)
|
.setReserveTxHash(reserveTxHash)
|
||||||
.setReserveTxHex(reserveTxHex)
|
.setReserveTxHex(reserveTxHex)
|
||||||
|
.addAllReserveTxKeyImages(reserveTxKeyImages)
|
||||||
.setArbitratorSignature(arbitratorSignature);
|
.setArbitratorSignature(arbitratorSignature);
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SignedOffer fromProto(protobuf.SignedOffer proto) {
|
public static SignedOffer fromProto(protobuf.SignedOffer proto) {
|
||||||
return new SignedOffer(proto.getOfferId(), proto.getReserveTxHash(), proto.getReserveTxHex(), proto.getArbitratorSignature());
|
return new SignedOffer(proto.getTimeStamp(), proto.getOfferId(), proto.getReserveTxHash(), proto.getReserveTxHex(), proto.getReserveTxKeyImagesList(), proto.getArbitratorSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,9 +78,11 @@ public final class SignedOffer implements PersistablePayload {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "SignedOffer{" +
|
return "SignedOffer{" +
|
||||||
|
",\n timeStamp=" + timeStamp +
|
||||||
",\n offerId=" + offerId +
|
",\n offerId=" + offerId +
|
||||||
",\n reserveTxHash=" + reserveTxHash +
|
",\n reserveTxHash=" + reserveTxHash +
|
||||||
",\n reserveTxHex=" + reserveTxHex +
|
",\n reserveTxHex=" + reserveTxHex +
|
||||||
|
",\n reserveTxKeyImages=" + reserveTxKeyImages +
|
||||||
",\n arbitratorSignature=" + arbitratorSignature +
|
",\n arbitratorSignature=" + arbitratorSignature +
|
||||||
"\n}";
|
"\n}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -487,7 +487,11 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||||
|
|
||||||
((ArbitratorProtocol) getTradeProtocol(trade)).handleInitTradeRequest(request, sender, errorMessage -> {
|
((ArbitratorProtocol) getTradeProtocol(trade)).handleInitTradeRequest(request, sender, errorMessage -> {
|
||||||
log.warn("Arbitrator error during trade initialization for trade {}: {}", trade.getId(), errorMessage);
|
log.warn("Arbitrator error during trade initialization for trade {}: {}", trade.getId(), errorMessage);
|
||||||
|
if (trade.getMaker().getReserveTxHash() != null || trade.getTaker().getReserveTxHash() != null) {
|
||||||
|
onMoveInvalidTradeToFailedTrades(trade); // arbitrator retains failed trades for analysis and penalty
|
||||||
|
} else {
|
||||||
removeTradeOnError(trade);
|
removeTradeOnError(trade);
|
||||||
|
}
|
||||||
if (takeOfferRequestErrorMessageHandler != null) takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage);
|
if (takeOfferRequestErrorMessageHandler != null) takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ public class OfferBook {
|
||||||
// Use offer.equals(offer) to see if the OfferBook list contains an exact
|
// Use offer.equals(offer) to see if the OfferBook list contains an exact
|
||||||
// match -- offer.equals(offer) includes comparisons of payload, state
|
// match -- offer.equals(offer) includes comparisons of payload, state
|
||||||
// and errorMessage.
|
// and errorMessage.
|
||||||
|
synchronized (offerBookListItems) {
|
||||||
boolean hasSameOffer = offerBookListItems.stream().anyMatch(item -> item.getOffer().equals(offer));
|
boolean hasSameOffer = offerBookListItems.stream().anyMatch(item -> item.getOffer().equals(offer));
|
||||||
if (!hasSameOffer) {
|
if (!hasSameOffer) {
|
||||||
OfferBookListItem newOfferBookListItem = new OfferBookListItem(offer);
|
OfferBookListItem newOfferBookListItem = new OfferBookListItem(offer);
|
||||||
|
@ -105,13 +106,16 @@ public class OfferBook {
|
||||||
}
|
}
|
||||||
printOfferBookListItems("After onAdded");
|
printOfferBookListItems("After onAdded");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRemoved(Offer offer) {
|
public void onRemoved(Offer offer) {
|
||||||
|
synchronized (offerBookListItems) {
|
||||||
printOfferBookListItems("Before onRemoved");
|
printOfferBookListItems("Before onRemoved");
|
||||||
removeOffer(offer);
|
removeOffer(offer);
|
||||||
printOfferBookListItems("After onRemoved");
|
printOfferBookListItems("After onRemoved");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
filterManager.filterProperty().addListener((observable, oldValue, newValue) -> {
|
filterManager.filterProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
@ -122,7 +126,9 @@ public class OfferBook {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeDuplicateItem(OfferBookListItem newOfferBookListItem) {
|
private void removeDuplicateItem(OfferBookListItem newOfferBookListItem) {
|
||||||
|
synchronized (offerBookListItems) {
|
||||||
String offerId = newOfferBookListItem.getOffer().getId();
|
String offerId = newOfferBookListItem.getOffer().getId();
|
||||||
|
|
||||||
// We need to remove any view items with a matching offerId before
|
// We need to remove any view items with a matching offerId before
|
||||||
// a newOfferBookListItem is added to the view.
|
// a newOfferBookListItem is added to the view.
|
||||||
List<OfferBookListItem> duplicateItems = offerBookListItems.stream()
|
List<OfferBookListItem> duplicateItems = offerBookListItems.stream()
|
||||||
|
@ -140,8 +146,11 @@ public class OfferBook {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removeOffer(Offer offer) {
|
public void removeOffer(Offer offer) {
|
||||||
|
synchronized (offerBookListItems) {
|
||||||
|
|
||||||
// Update state in case that that offer is used in the take offer screen, so it gets updated correctly
|
// Update state in case that that offer is used in the take offer screen, so it gets updated correctly
|
||||||
offer.setState(Offer.State.REMOVED);
|
offer.setState(Offer.State.REMOVED);
|
||||||
offer.cancelAvailabilityRequest();
|
offer.cancelAvailabilityRequest();
|
||||||
|
@ -196,12 +205,14 @@ public class OfferBook {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ObservableList<OfferBookListItem> getOfferBookListItems() {
|
public ObservableList<OfferBookListItem> getOfferBookListItems() {
|
||||||
return offerBookListItems;
|
return offerBookListItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fillOfferBookListItems() {
|
public void fillOfferBookListItems() {
|
||||||
|
synchronized (offerBookListItems) {
|
||||||
try {
|
try {
|
||||||
// setAll causes sometimes an UnsupportedOperationException
|
// setAll causes sometimes an UnsupportedOperationException
|
||||||
// Investigate why....
|
// Investigate why....
|
||||||
|
@ -217,8 +228,10 @@ public class OfferBook {
|
||||||
log.error("Error at fillOfferBookListItems: " + t);
|
log.error("Error at fillOfferBookListItems: " + t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void printOfferBookListItems(String msg) {
|
public void printOfferBookListItems(String msg) {
|
||||||
|
synchronized (offerBookListItems) {
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
if (offerBookListItems.size() == 0) {
|
if (offerBookListItems.size() == 0) {
|
||||||
log.debug("{} -> OfferBookListItems: none", msg);
|
log.debug("{} -> OfferBookListItems: none", msg);
|
||||||
|
@ -231,6 +244,7 @@ public class OfferBook {
|
||||||
log.debug(stringBuilder.toString());
|
log.debug(stringBuilder.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String, Integer> getBuyOfferCountMap() {
|
public Map<String, Integer> getBuyOfferCountMap() {
|
||||||
return buyOfferCountMap;
|
return buyOfferCountMap;
|
||||||
|
|
|
@ -319,13 +319,16 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
||||||
String sellerWitnessHash = trade.getSeller().getAccountAgeWitness() == null ? "null" : Utilities.bytesAsHexString(trade.getSeller().getAccountAgeWitness().getHash());
|
String sellerWitnessHash = trade.getSeller().getAccountAgeWitness() == null ? "null" : Utilities.bytesAsHexString(trade.getSeller().getAccountAgeWitness().getHash());
|
||||||
String sellerPubKeyRingHash = Utilities.bytesAsHexString(trade.getSeller().getPubKeyRing().getSignaturePubKeyBytes());
|
String sellerPubKeyRingHash = Utilities.bytesAsHexString(trade.getSeller().getPubKeyRing().getSignaturePubKeyBytes());
|
||||||
|
|
||||||
if (contract != null) {
|
|
||||||
viewContractButton.setOnAction(e -> {
|
viewContractButton.setOnAction(e -> {
|
||||||
TextArea textArea = new HavenoTextArea();
|
TextArea textArea = new HavenoTextArea();
|
||||||
textArea.setText(trade.getContractAsJson());
|
textArea.setText(trade.getContractAsJson());
|
||||||
String data = "Contract as json:\n";
|
String data = "Contract as json:\n";
|
||||||
data += trade.getContractAsJson();
|
data += trade.getContractAsJson();
|
||||||
data += "\n\nOther detail data:";
|
data += "\n\nOther detail data:";
|
||||||
|
if (!trade.isDepositPublished()) {
|
||||||
|
data += "\n\n" + (trade.getMaker() == trade.getBuyer() ? "Buyer" : "Seller") + " as maker reserve tx hex: " + trade.getMaker().getReserveTxHex();
|
||||||
|
data += "\n\n" + (trade.getTaker() == trade.getBuyer() ? "Buyer" : "Seller") + " as taker reserve tx hex: " + trade.getTaker().getReserveTxHex();
|
||||||
|
}
|
||||||
if (offer.isFiatOffer()) {
|
if (offer.isFiatOffer()) {
|
||||||
data += "\n\nBuyers witness hash,pub key ring hash: " + buyerWitnessHash + "," + buyerPubKeyRingHash;
|
data += "\n\nBuyers witness hash,pub key ring hash: " + buyerWitnessHash + "," + buyerPubKeyRingHash;
|
||||||
data += "\nBuyers account age: " + buyersAccountAge;
|
data += "\nBuyers account age: " + buyersAccountAge;
|
||||||
|
@ -339,7 +342,8 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
||||||
// data += "\n\nRaw deposit transaction as hex:\n" + depositTxAsHex;
|
// data += "\n\nRaw deposit transaction as hex:\n" + depositTxAsHex;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
data += "\n\nSelected arbitrator: " + DisputeAgentLookupMap.getMatrixUserName(contract.getArbitratorNodeAddress().getFullAddress());
|
|
||||||
|
data += "\n\nSelected arbitrator: " + trade.getArbitrator().getNodeAddress();
|
||||||
|
|
||||||
textArea.setText(data);
|
textArea.setText(data);
|
||||||
textArea.setPrefHeight(50);
|
textArea.setPrefHeight(50);
|
||||||
|
@ -375,7 +379,6 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
closeButton.setOnAction(e -> {
|
closeButton.setOnAction(e -> {
|
||||||
closeHandlerOptional.ifPresent(Runnable::run);
|
closeHandlerOptional.ifPresent(Runnable::run);
|
||||||
|
|
|
@ -445,11 +445,11 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
|
||||||
return FilterResult.SELLER_NODE_ADDRESS;
|
return FilterResult.SELLER_NODE_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dispute.getBuyerPaymentAccountPayload().getPaymentDetails().toLowerCase().contains(filter)) {
|
if (dispute.getBuyerPaymentAccountPayload() != null && dispute.getBuyerPaymentAccountPayload().getPaymentDetails().toLowerCase().contains(filter)) {
|
||||||
return FilterResult.BUYER_ACCOUNT_DETAILS;
|
return FilterResult.BUYER_ACCOUNT_DETAILS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dispute.getSellerPaymentAccountPayload().getPaymentDetails().toLowerCase().contains(filter)) {
|
if (dispute.getSellerPaymentAccountPayload() != null && dispute.getSellerPaymentAccountPayload().getPaymentDetails().toLowerCase().contains(filter)) {
|
||||||
return FilterResult.SELLER_ACCOUNT_DETAILS;
|
return FilterResult.SELLER_ACCOUNT_DETAILS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1509,10 +1509,12 @@ message SignedOfferList {
|
||||||
}
|
}
|
||||||
|
|
||||||
message SignedOffer {
|
message SignedOffer {
|
||||||
string offer_id = 1;
|
int64 time_stamp = 1;
|
||||||
string reserve_tx_hash = 2;
|
string offer_id = 2;
|
||||||
string reserve_tx_hex = 3;
|
string reserve_tx_hash = 3;
|
||||||
string arbitrator_signature = 4;
|
string reserve_tx_hex = 4;
|
||||||
|
repeated string reserve_tx_key_images = 5;
|
||||||
|
string arbitrator_signature = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message OpenOffer {
|
message OpenOffer {
|
||||||
|
|
Loading…
Reference in a new issue