Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix account age display of peer #2753

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.TradingPeer;
import bisq.core.user.User;

import bisq.network.p2p.BootstrapListener;
Expand Down Expand Up @@ -161,7 +162,7 @@ private AccountAgeWitness getNewWitness(PaymentAccountPayload paymentAccountPayl
return new AccountAgeWitness(hash, new Date().getTime());
}

private Optional<AccountAgeWitness> findWitness(PaymentAccountPayload paymentAccountPayload, PubKeyRing pubKeyRing) {
public Optional<AccountAgeWitness> findWitness(PaymentAccountPayload paymentAccountPayload, PubKeyRing pubKeyRing) {
byte[] accountInputDataWithSalt = getAccountInputDataWithSalt(paymentAccountPayload);
byte[] hash = Hash.getSha256Ripemd160hash(Utilities.concatenateByteArrays(accountInputDataWithSalt,
pubKeyRing.getSignaturePubKeyBytes()));
Expand All @@ -188,6 +189,12 @@ public long getAccountAge(AccountAgeWitness accountAgeWitness, Date now) {
return now.getTime() - accountAgeWitness.getDate();
}

public long getAccountAge(PaymentAccountPayload paymentAccountPayload, PubKeyRing pubKeyRing) {
return findWitness(paymentAccountPayload, pubKeyRing)
.map(accountAgeWitness -> getAccountAge(accountAgeWitness, new Date()))
.orElse(-1L);
}

public AccountAge getAccountAgeCategory(long accountAge) {
if (accountAge < TimeUnit.DAYS.toMillis(30)) {
return AccountAge.LESS_ONE_MONTH;
Expand Down Expand Up @@ -286,6 +293,16 @@ public long getMakersAccountAge(Offer offer, Date peersCurrentDate) {
.orElse(-1L);
}

public long getTradingPeersAccountAge(Trade trade) {
TradingPeer tradingPeer = trade.getProcessModel().getTradingPeer();
if (tradingPeer.getPaymentAccountPayload() == null || tradingPeer.getPubKeyRing() == null) {
// unexpected
return -1;
}

return getAccountAge(tradingPeer.getPaymentAccountPayload(), tradingPeer.getPubKeyRing());
}


///////////////////////////////////////////////////////////////////////////////////////////
// Verification
Expand Down
1 change: 1 addition & 0 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,7 @@ contractWindow.title=Dispute details
contractWindow.dates=Offer date / Trade date
contractWindow.btcAddresses=Bitcoin address BTC buyer / BTC seller
contractWindow.onions=Network address BTC buyer / BTC seller
contractWindow.accountAge=Account age BTC buyer / BTC seller
contractWindow.numDisputes=No. of disputes BTC buyer / BTC seller
contractWindow.contractHash=Contract hash

Expand Down
96 changes: 89 additions & 7 deletions desktop/src/main/java/bisq/desktop/components/PeerInfoIcon.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import bisq.core.locale.Res;
import bisq.core.offer.Offer;
import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.trade.Trade;
import bisq.core.user.Preferences;
import bisq.core.util.BSFormatter;

Expand All @@ -48,10 +49,15 @@

import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nullable;

import static com.google.common.base.Preconditions.checkNotNull;

@Slf4j
public class PeerInfoIcon extends Group {
private final String tooltipText;
private final int numTrades;
private final AccountAgeWitnessService accountAgeWitnessService;
private final Map<String, String> peerTagMap;
private final Label numTradesLabel;
private final Label tagLabel;
Expand All @@ -69,18 +75,71 @@ public PeerInfoIcon(NodeAddress nodeAddress,
AccountAgeWitnessService accountAgeWitnessService,
BSFormatter formatter,
boolean useDevPrivilegeKeys) {
this(nodeAddress,
role,
numTrades,
privateNotificationManager,
offer,
null,
preferences,
accountAgeWitnessService,
formatter,
useDevPrivilegeKeys);

}

public PeerInfoIcon(NodeAddress nodeAddress,
String role,
int numTrades,
PrivateNotificationManager privateNotificationManager,
Trade trade,
Preferences preferences,
AccountAgeWitnessService accountAgeWitnessService,
BSFormatter formatter,
boolean useDevPrivilegeKeys) {
this(nodeAddress,
role,
numTrades,
privateNotificationManager,
null,
trade,
preferences,
accountAgeWitnessService,
formatter,
useDevPrivilegeKeys);
}

private PeerInfoIcon(NodeAddress nodeAddress,
String role,
int numTrades,
PrivateNotificationManager privateNotificationManager,
@Nullable Offer offer,
@Nullable Trade trade,
Preferences preferences,
AccountAgeWitnessService accountAgeWitnessService,
BSFormatter formatter,
boolean useDevPrivilegeKeys) {
this.numTrades = numTrades;
this.accountAgeWitnessService = accountAgeWitnessService;

scaleFactor = getScaleFactor();
fullAddress = nodeAddress != null ? nodeAddress.getFullAddress() : "";

peerTagMap = preferences.getPeerTagMap();

boolean hasTraded = numTrades > 0;
final boolean isFiatCurrency = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode());
final long makersAccountAge = accountAgeWitnessService.getMakersAccountAge(offer, new Date());
final String accountAge = isFiatCurrency ?
makersAccountAge > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(makersAccountAge)) :
long peersAccountAge = getPeersAccountAge(trade, offer);
if (offer == null) {
checkNotNull(trade, "Trade must not be null if offer is null.");
offer = trade.getOffer();
}

checkNotNull(offer, "Offer must not be null");

boolean isFiatCurrency = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode());

String accountAge = isFiatCurrency ?
peersAccountAge > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(peersAccountAge)) :
Res.get("peerInfoIcon.tooltip.unknownAge") :
"";
tooltipText = hasTraded ?
Expand All @@ -90,7 +149,7 @@ public PeerInfoIcon(NodeAddress nodeAddress,
// outer circle
Color ringColor;
if (isFiatCurrency) {
switch (accountAgeWitnessService.getAccountAgeCategory(makersAccountAge)) {
switch (accountAgeWitnessService.getAccountAgeCategory(peersAccountAge)) {
case TWO_MONTHS_OR_MORE:
ringColor = Color.rgb(0, 225, 0); // > 2 months green
break;
Expand Down Expand Up @@ -178,10 +237,33 @@ public PeerInfoIcon(NodeAddress nodeAddress,

getChildren().addAll(outerBackground, innerBackground, avatarImageView, tagPane, numTradesPane);

addMouseListener(numTrades, privateNotificationManager, offer, preferences, formatter, useDevPrivilegeKeys, isFiatCurrency, makersAccountAge);
addMouseListener(numTrades, privateNotificationManager, offer, preferences, formatter, useDevPrivilegeKeys, isFiatCurrency, peersAccountAge);
}

private long getPeersAccountAge(@Nullable Trade trade, @Nullable Offer offer) {
if (trade != null) {
offer = trade.getOffer();
if (offer == null) {
// unexpected
return -1;
}

return accountAgeWitnessService.getTradingPeersAccountAge(trade);
} else {
checkNotNull(offer, "Offer must not be null if trade is null.");

return accountAgeWitnessService.getMakersAccountAge(offer, new Date());
}
}

protected void addMouseListener(int numTrades, PrivateNotificationManager privateNotificationManager, Offer offer, Preferences preferences, BSFormatter formatter, boolean useDevPrivilegeKeys, boolean isFiatCurrency, long makersAccountAge) {
protected void addMouseListener(int numTrades,
PrivateNotificationManager privateNotificationManager,
Offer offer,
Preferences preferences,
BSFormatter formatter,
boolean useDevPrivilegeKeys,
boolean isFiatCurrency,
long makersAccountAge) {
final String accountAgeTagEditor = isFiatCurrency ?
makersAccountAge > -1 ?
formatter.formatAccountAge(makersAccountAge) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,22 @@
import bisq.network.p2p.NodeAddress;

public class PeerInfoIconSmall extends PeerInfoIcon {
public PeerInfoIconSmall(NodeAddress nodeAddress, String role, Offer offer, Preferences preferences, AccountAgeWitnessService accountAgeWitnessService, BSFormatter formatter, boolean useDevPrivilegeKeys) {
public PeerInfoIconSmall(NodeAddress nodeAddress,
String role, Offer offer,
Preferences preferences,
AccountAgeWitnessService accountAgeWitnessService,
BSFormatter formatter,
boolean useDevPrivilegeKeys) {
// We don't want to show number of trades in that case as it would be unreadable.
// Also we don't need the privateNotificationManager as no interaction will take place with this icon.
super(nodeAddress, role, 0, null, offer, preferences, accountAgeWitnessService, formatter, useDevPrivilegeKeys);
super(nodeAddress, role,
0,
null,
offer,
preferences,
accountAgeWitnessService,
formatter,
useDevPrivilegeKeys);
}

@Override
Expand All @@ -21,7 +33,13 @@ protected double getScaleFactor() {
}

@Override
protected void addMouseListener(int numTrades, PrivateNotificationManager privateNotificationManager, Offer offer, Preferences preferences, BSFormatter formatter, boolean useDevPrivilegeKeys, boolean isFiatCurrency, long makersAccountAge) {
protected void addMouseListener(int numTrades,
PrivateNotificationManager privateNotificationManager,
Offer offer, Preferences preferences,
BSFormatter formatter,
boolean useDevPrivilegeKeys,
boolean isFiatCurrency,
long makersAccountAge) {
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import bisq.core.alert.PrivateNotificationManager;
import bisq.core.app.AppOptionKeys;
import bisq.core.arbitration.DisputeManager;
import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.trade.TradeManager;
import bisq.core.util.BSFormatter;

Expand All @@ -41,14 +42,28 @@
public class ArbitratorDisputeView extends TraderDisputeView {

@Inject
public ArbitratorDisputeView(DisputeManager disputeManager, KeyRing keyRing, TradeManager tradeManager,
BSFormatter formatter, DisputeSummaryWindow disputeSummaryWindow,
public ArbitratorDisputeView(DisputeManager disputeManager,
KeyRing keyRing,
TradeManager tradeManager,
BSFormatter formatter,
DisputeSummaryWindow disputeSummaryWindow,
PrivateNotificationManager privateNotificationManager,
ContractWindow contractWindow, TradeDetailsWindow tradeDetailsWindow,
P2PService p2PService, @Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) {
super(disputeManager, keyRing, tradeManager, formatter,
disputeSummaryWindow, privateNotificationManager, contractWindow,
tradeDetailsWindow, p2PService, useDevPrivilegeKeys);
ContractWindow contractWindow,
TradeDetailsWindow tradeDetailsWindow,
P2PService p2PService,
AccountAgeWitnessService accountAgeWitnessService,
@Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) {
super(disputeManager,
keyRing,
tradeManager,
formatter,
disputeSummaryWindow,
privateNotificationManager,
contractWindow,
tradeDetailsWindow,
p2PService,
accountAgeWitnessService,
useDevPrivilegeKeys);
}

@Override
Expand All @@ -65,8 +80,8 @@ protected void applyFilteredListPredicate(String filterString) {
filteredList.setPredicate(dispute -> {
boolean matchesTradeId = dispute.getTradeId().contains(filterString);
boolean matchesDate = formatter.formatDate(dispute.getOpeningDate()).contains(filterString);
boolean isBuyerOnion = getBuyerOnionAddressColumnLabel(dispute).contains(filterString);
boolean isSellerOnion = getSellerOnionAddressColumnLabel(dispute).contains(filterString);
boolean isBuyerOnion = dispute.getContract().getBuyerNodeAddress().getFullAddress().contains(filterString);
boolean isSellerOnion = dispute.getContract().getSellerNodeAddress().getFullAddress().contains(filterString);
boolean matchesBuyersPaymentAccountData = dispute.getContract().getBuyerPaymentAccountPayload().getPaymentDetails().contains(filterString);
boolean matchesSellersPaymentAccountData = dispute.getContract().getSellerPaymentAccountPayload().getPaymentDetails().contains(filterString);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
import bisq.core.arbitration.Dispute;
import bisq.core.arbitration.DisputeManager;
import bisq.core.arbitration.messages.DisputeCommunicationMessage;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.trade.Contract;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager;
Expand Down Expand Up @@ -147,6 +149,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
private final P2PService p2PService;

private final List<Attachment> tempAttachments = new ArrayList<>();
private final AccountAgeWitnessService accountAgeWitnessService;
private final boolean useDevPrivilegeKeys;

private TableView<Dispute> tableView;
Expand Down Expand Up @@ -192,6 +195,7 @@ public TraderDisputeView(DisputeManager disputeManager,
ContractWindow contractWindow,
TradeDetailsWindow tradeDetailsWindow,
P2PService p2PService,
AccountAgeWitnessService accountAgeWitnessService,
@Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) {
this.disputeManager = disputeManager;
this.keyRing = keyRing;
Expand All @@ -202,6 +206,7 @@ public TraderDisputeView(DisputeManager disputeManager,
this.contractWindow = contractWindow;
this.tradeDetailsWindow = tradeDetailsWindow;
this.p2PService = p2PService;
this.accountAgeWitnessService = accountAgeWitnessService;
this.useDevPrivilegeKeys = useDevPrivilegeKeys;
}

Expand Down Expand Up @@ -1161,7 +1166,7 @@ public void updateItem(final Dispute item, boolean empty) {
private TableColumn<Dispute, Dispute> getBuyerOnionAddressColumn() {
TableColumn<Dispute, Dispute> column = new AutoTooltipTableColumn<>(Res.get("support.buyerAddress")) {
{
setMinWidth(170);
setMinWidth(190);
}
};
column.setCellValueFactory((dispute) -> new ReadOnlyObjectWrapper<>(dispute.getValue()));
Expand All @@ -1187,7 +1192,7 @@ public void updateItem(final Dispute item, boolean empty) {
private TableColumn<Dispute, Dispute> getSellerOnionAddressColumn() {
TableColumn<Dispute, Dispute> column = new AutoTooltipTableColumn<>(Res.get("support.sellerAddress")) {
{
setMinWidth(170);
setMinWidth(190);
}
};
column.setCellValueFactory((dispute) -> new ReadOnlyObjectWrapper<>(dispute.getValue()));
Expand Down Expand Up @@ -1215,9 +1220,13 @@ protected String getBuyerOnionAddressColumnLabel(Dispute item) {
Contract contract = item.getContract();
if (contract != null) {
NodeAddress buyerNodeAddress = contract.getBuyerNodeAddress();
if (buyerNodeAddress != null)
return buyerNodeAddress.getHostNameWithoutPostFix() + " (" + disputeManager.getNrOfDisputes(true, contract) + ")";
else
if (buyerNodeAddress != null) {
String nrOfDisputes = disputeManager.getNrOfDisputes(true, contract);
long accountAge = accountAgeWitnessService.getAccountAge(contract.getBuyerPaymentAccountPayload(), contract.getBuyerPubKeyRing());
String age = formatter.formatAccountAge(accountAge);
String postFix = CurrencyUtil.isFiatCurrency(item.getContract().getOfferPayload().getCurrencyCode()) ? " / " + age : "";
return buyerNodeAddress.getHostNameWithoutPostFix() + " (" + nrOfDisputes + postFix + ")";
} else
return Res.get("shared.na");
} else {
return Res.get("shared.na");
Expand All @@ -1228,9 +1237,13 @@ protected String getSellerOnionAddressColumnLabel(Dispute item) {
Contract contract = item.getContract();
if (contract != null) {
NodeAddress sellerNodeAddress = contract.getSellerNodeAddress();
if (sellerNodeAddress != null)
return sellerNodeAddress.getHostNameWithoutPostFix() + " (" + disputeManager.getNrOfDisputes(false, contract) + ")";
else
if (sellerNodeAddress != null) {
String nrOfDisputes = disputeManager.getNrOfDisputes(false, contract);
long accountAge = accountAgeWitnessService.getAccountAge(contract.getSellerPaymentAccountPayload(), contract.getSellerPubKeyRing());
String age = formatter.formatAccountAge(accountAge);
String postFix = CurrencyUtil.isFiatCurrency(item.getContract().getOfferPayload().getCurrencyCode()) ? " / " + age : "";
return sellerNodeAddress.getHostNameWithoutPostFix() + " (" + nrOfDisputes + postFix + ")";
} else
return Res.get("shared.na");
} else {
return Res.get("shared.na");
Expand All @@ -1240,7 +1253,7 @@ protected String getSellerOnionAddressColumnLabel(Dispute item) {
private TableColumn<Dispute, Dispute> getMarketColumn() {
TableColumn<Dispute, Dispute> column = new AutoTooltipTableColumn<>(Res.get("shared.market")) {
{
setMinWidth(130);
setMinWidth(80);
}
};
column.setCellValueFactory((dispute) -> new ReadOnlyObjectWrapper<>(dispute.getValue()));
Expand Down
Loading