mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-29 01:38:39 -04:00
Bugfixes, refactorings,...
This commit is contained in:
parent
d933110a8d
commit
9dd9decb96
22 changed files with 124 additions and 82 deletions
|
@ -121,7 +121,7 @@ public class AddressEntry implements Serializable {
|
||||||
// For display we usually only display the first 8 characters.
|
// For display we usually only display the first 8 characters.
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getShortOfferId() {
|
public String getShortOfferId() {
|
||||||
return offerId != null ? offerId.substring(0, 8) : null;
|
return offerId != null ? offerId.substring(0, Math.min(8, offerId.length())) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context getContext() {
|
public Context getContext() {
|
||||||
|
|
|
@ -968,7 +968,7 @@ public class TradeWalletService {
|
||||||
checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
|
checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
|
||||||
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
||||||
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
|
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
|
||||||
checkNotNull(sigKey, "sigKey must not be null");
|
checkNotNull(sigKey, "signInput: sigKey must not be null. input.getOutpoint()=" + input.getOutpoint().toString());
|
||||||
Sha256Hash hash = transaction.hashForSignature(inputIndex, scriptPubKey, Transaction.SigHash.ALL, false);
|
Sha256Hash hash = transaction.hashForSignature(inputIndex, scriptPubKey, Transaction.SigHash.ALL, false);
|
||||||
ECKey.ECDSASignature signature = sigKey.sign(hash, aesKey);
|
ECKey.ECDSASignature signature = sigKey.sign(hash, aesKey);
|
||||||
TransactionSignature txSig = new TransactionSignature(signature, Transaction.SigHash.ALL, false);
|
TransactionSignature txSig = new TransactionSignature(signature, Transaction.SigHash.ALL, false);
|
||||||
|
|
|
@ -26,6 +26,7 @@ public class BlockChainAccountContractData extends PaymentAccountContractData im
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
private String address;
|
private String address;
|
||||||
|
// used in crypto note coins. not supported now but hopefully in future, so leave it for now.
|
||||||
private String paymentId;
|
private String paymentId;
|
||||||
|
|
||||||
public BlockChainAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
public BlockChainAccountContractData(String paymentMethod, String id, int maxTradePeriod) {
|
||||||
|
|
|
@ -198,7 +198,7 @@ public final class Offer implements PubKeyProtectedExpirablePayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getReferenceText() {
|
public String getReferenceText() {
|
||||||
return id.substring(0, 8);
|
return id.substring(0, Math.min(8, id.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ public final class Offer implements PubKeyProtectedExpirablePayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getShortId() {
|
public String getShortId() {
|
||||||
return id.substring(0, 8);
|
return id.substring(0, Math.min(8, id.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeAddress getOffererNodeAddress() {
|
public NodeAddress getOffererNodeAddress() {
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class ProcessPayDepositRequest extends TradeTask {
|
||||||
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
|
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
|
||||||
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
||||||
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
|
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
|
||||||
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, 32);
|
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, Math.min(32, trade.getId().length()));
|
||||||
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
|
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class ProcessPublishDepositTxRequest extends TradeTask {
|
||||||
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
|
// We apply the payment ID in case its a cryptoNote coin. It is created form the hash of the trade ID
|
||||||
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
||||||
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
|
CurrencyUtil.isCryptoNoteCoin(processModel.getOffer().getCurrencyCode())) {
|
||||||
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, 32);
|
String paymentId = Hash.getHashAsHex(trade.getId()).substring(0, Math.min(32, trade.getId().length()));
|
||||||
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
|
((BlockChainAccountContractData) paymentAccountContractData).setPaymentId(paymentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,13 +27,11 @@ import javafx.scene.control.TextField;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public class TextFieldWithCopyIcon extends AnchorPane {
|
public class TextFieldWithCopyIcon extends AnchorPane {
|
||||||
|
|
||||||
private final StringProperty text = new SimpleStringProperty();
|
private final StringProperty text = new SimpleStringProperty();
|
||||||
private final TextField textField;
|
private final TextField textField;
|
||||||
private Consumer<String> handler;
|
private boolean copyWithoutCurrencyPostFix;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -48,10 +46,19 @@ public class TextFieldWithCopyIcon extends AnchorPane {
|
||||||
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
|
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
|
||||||
AnchorPane.setRightAnchor(copyIcon, 0.0);
|
AnchorPane.setRightAnchor(copyIcon, 0.0);
|
||||||
copyIcon.setOnMouseClicked(e -> {
|
copyIcon.setOnMouseClicked(e -> {
|
||||||
if (getText() != null && getText().length() > 0) {
|
String text = getText();
|
||||||
Utilities.copyToClipboard(getText());
|
if (text != null && text.length() > 0) {
|
||||||
if (handler != null)
|
String copyText;
|
||||||
handler.accept(getText());
|
if (copyWithoutCurrencyPostFix) {
|
||||||
|
String[] strings = text.split(" ");
|
||||||
|
if (strings.length > 1)
|
||||||
|
copyText = strings[0]; // exclude the BTC postfix
|
||||||
|
else
|
||||||
|
copyText = text;
|
||||||
|
} else {
|
||||||
|
copyText = text;
|
||||||
|
}
|
||||||
|
Utilities.copyToClipboard(copyText);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
textField = new TextField();
|
textField = new TextField();
|
||||||
|
@ -85,7 +92,8 @@ public class TextFieldWithCopyIcon extends AnchorPane {
|
||||||
this.text.set(text);
|
this.text.set(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHandler(Consumer<String> handler) {
|
public void setCopyWithoutCurrencyPostFix(boolean copyWithoutCurrencyPostFix) {
|
||||||
this.handler = handler;
|
this.copyWithoutCurrencyPostFix = copyWithoutCurrencyPostFix;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,20 +54,20 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
|
|
||||||
public static final String TITLE_KEY = "view.title";
|
public static final String TITLE_KEY = "view.title";
|
||||||
|
|
||||||
public static BorderPane getBaseApplicationContainer() {
|
public static StackPane getRootContainer() {
|
||||||
return baseApplicationContainer;
|
return MainView.rootContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void blur() {
|
public static void blur() {
|
||||||
transitions.blur(MainView.base);
|
transitions.blur(MainView.rootContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void blurLight() {
|
public static void blurLight() {
|
||||||
transitions.blur(MainView.base, Transitions.DEFAULT_DURATION, true, false, 5);
|
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, true, false, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeBlur() {
|
public static void removeBlur() {
|
||||||
transitions.removeBlur(baseApplicationContainer);
|
transitions.removeBlur(MainView.rootContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ToggleGroup navButtons = new ToggleGroup();
|
private final ToggleGroup navButtons = new ToggleGroup();
|
||||||
|
@ -86,9 +86,9 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
private ProgressBar btcSyncIndicator;
|
private ProgressBar btcSyncIndicator;
|
||||||
private Label btcSplashInfo;
|
private Label btcSplashInfo;
|
||||||
private List<String> persistedFilesCorrupted;
|
private List<String> persistedFilesCorrupted;
|
||||||
private static BorderPane baseApplicationContainer;
|
private BorderPane baseApplicationContainer;
|
||||||
private static StackPane base;
|
|
||||||
private Popup p2PNetworkWarnMsgPopup, btcNetworkWarnMsgPopup;
|
private Popup p2PNetworkWarnMsgPopup, btcNetworkWarnMsgPopup;
|
||||||
|
private static StackPane rootContainer;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MainView(MainViewModel model, CachingViewLoader viewLoader, Navigation navigation, Transitions transitions,
|
public MainView(MainViewModel model, CachingViewLoader viewLoader, Navigation navigation, Transitions transitions,
|
||||||
|
@ -102,7 +102,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initialize() {
|
protected void initialize() {
|
||||||
MainView.base = this.root;
|
MainView.rootContainer = this.root;
|
||||||
|
|
||||||
ToggleButton marketButton = new NavButton(MarketView.class, "Market");
|
ToggleButton marketButton = new NavButton(MarketView.class, "Market");
|
||||||
ToggleButton buyButton = new NavButton(BuyOfferView.class, "Buy BTC");
|
ToggleButton buyButton = new NavButton(BuyOfferView.class, "Buy BTC");
|
||||||
|
|
|
@ -225,7 +225,8 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||||
private void onRequestUpload() {
|
private void onRequestUpload() {
|
||||||
if (tempAttachments.size() < 3) {
|
if (tempAttachments.size() < 3) {
|
||||||
FileChooser fileChooser = new FileChooser();
|
FileChooser fileChooser = new FileChooser();
|
||||||
fileChooser.setTitle("Open file to attach");
|
int maxSizeInKB = Connection.getMaxMsgSize() / 1024;
|
||||||
|
fileChooser.setTitle("Open file to attach (max. file size: " + maxSizeInKB + " kb)");
|
||||||
/* if (Utilities.isUnix())
|
/* if (Utilities.isUnix())
|
||||||
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));*/
|
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));*/
|
||||||
File result = fileChooser.showOpenDialog(stage);
|
File result = fileChooser.showOpenDialog(stage);
|
||||||
|
@ -238,7 +239,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||||
tempAttachments.add(new DisputeDirectMessage.Attachment(result.getName(), filesAsBytes));
|
tempAttachments.add(new DisputeDirectMessage.Attachment(result.getName(), filesAsBytes));
|
||||||
inputTextArea.setText(inputTextArea.getText() + "\n[Attachment " + result.getName() + "]");
|
inputTextArea.setText(inputTextArea.getText() + "\n[Attachment " + result.getName() + "]");
|
||||||
} else {
|
} else {
|
||||||
new Popup().error("The max. allowed file size is 100 kB.").show();
|
new Popup().error("The max. allowed file size is " + maxSizeInKB + " kB.").show();
|
||||||
}
|
}
|
||||||
} catch (java.io.IOException e) {
|
} catch (java.io.IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -19,6 +19,7 @@ package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||||
|
|
||||||
import io.bitsquare.app.BitsquareApp;
|
import io.bitsquare.app.BitsquareApp;
|
||||||
import io.bitsquare.common.util.Tuple3;
|
import io.bitsquare.common.util.Tuple3;
|
||||||
|
import io.bitsquare.gui.components.TextFieldWithCopyIcon;
|
||||||
import io.bitsquare.gui.components.TitledGroupBg;
|
import io.bitsquare.gui.components.TitledGroupBg;
|
||||||
import io.bitsquare.gui.components.TxIdTextField;
|
import io.bitsquare.gui.components.TxIdTextField;
|
||||||
import io.bitsquare.gui.components.paymentmethods.*;
|
import io.bitsquare.gui.components.paymentmethods.*;
|
||||||
|
@ -208,8 +209,9 @@ public class StartPaymentView extends TradeStepDetailsView {
|
||||||
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
||||||
|
|
||||||
TitledGroupBg accountTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Payments details", Layout.GROUP_DISTANCE);
|
TitledGroupBg accountTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Payments details", Layout.GROUP_DISTANCE);
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, gridRow, "Amount to transfer:", model.getFiatAmount(),
|
TextFieldWithCopyIcon field = addLabelTextFieldWithCopyIcon(gridPane, gridRow, "Amount to transfer:", model.getFiatAmount(),
|
||||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||||
|
field.setCopyWithoutCurrencyPostFix(true);
|
||||||
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
|
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
|
||||||
|
|
||||||
String paymentMethodName = paymentAccountContractData.getPaymentMethodName();
|
String paymentMethodName = paymentAccountContractData.getPaymentMethodName();
|
||||||
|
|
|
@ -103,6 +103,7 @@ public class ContractPopup extends Popup {
|
||||||
if (sellerPaymentAccountContractData instanceof BlockChainAccountContractData &&
|
if (sellerPaymentAccountContractData instanceof BlockChainAccountContractData &&
|
||||||
((BlockChainAccountContractData) sellerPaymentAccountContractData).getPaymentId() != null) {
|
((BlockChainAccountContractData) sellerPaymentAccountContractData).getPaymentId() != null) {
|
||||||
rows++;
|
rows++;
|
||||||
|
isPaymentIdAvailable = true;
|
||||||
}
|
}
|
||||||
addTitledGroupBg(gridPane, ++rowIndex, rows, "Contract");
|
addTitledGroupBg(gridPane, ++rowIndex, rows, "Contract");
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, rowIndex, "Offer ID:", offer.getId(),
|
addLabelTextFieldWithCopyIcon(gridPane, rowIndex, "Offer ID:", offer.getId(),
|
||||||
|
@ -123,7 +124,7 @@ public class ContractPopup extends Popup {
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Selected arbitrator:", contract.arbitratorNodeAddress.getFullAddress());
|
addLabelTextField(gridPane, ++rowIndex, "Selected arbitrator:", contract.arbitratorNodeAddress.getFullAddress());
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Buyer payment details:",
|
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Buyer payment details:",
|
||||||
BSResources.get(contract.getBuyerPaymentAccountContractData().getPaymentDetails())).second.setMouseTransparent(false);
|
BSResources.get(contract.getBuyerPaymentAccountContractData().getPaymentDetails())).second.setMouseTransparent(false);
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Seller payment details:",
|
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Seller payment details:",
|
||||||
BSResources.get(sellerPaymentAccountContractData.getPaymentDetails())).second.setMouseTransparent(false);
|
BSResources.get(sellerPaymentAccountContractData.getPaymentDetails())).second.setMouseTransparent(false);
|
||||||
if (isPaymentIdAvailable)
|
if (isPaymentIdAvailable)
|
||||||
addLabelTextField(gridPane, ++rowIndex, "Seller payment ID:",
|
addLabelTextField(gridPane, ++rowIndex, "Seller payment ID:",
|
||||||
|
|
|
@ -208,7 +208,7 @@ public class Popup {
|
||||||
|
|
||||||
protected void createPopup() {
|
protected void createPopup() {
|
||||||
if (owner == null)
|
if (owner == null)
|
||||||
owner = MainView.getBaseApplicationContainer();
|
owner = MainView.getRootContainer();
|
||||||
|
|
||||||
stage = new Stage();
|
stage = new Stage();
|
||||||
Scene scene = new Scene(gridPane);
|
Scene scene = new Scene(gridPane);
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class NodeAddress implements Serializable {
|
||||||
// We use just a few chars form or address to blur the potential receiver for sent messages
|
// We use just a few chars form or address to blur the potential receiver for sent messages
|
||||||
public byte[] getAddressPrefixHash() {
|
public byte[] getAddressPrefixHash() {
|
||||||
if (addressPrefixHash == null)
|
if (addressPrefixHash == null)
|
||||||
addressPrefixHash = Hash.getHash(getFullAddress().substring(0, 2));
|
addressPrefixHash = Hash.getHash(getFullAddress().substring(0, Math.min(2, getFullAddress().length())));
|
||||||
return addressPrefixHash;
|
return addressPrefixHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
|
||||||
private ChangeListener<NodeAddress> connectionNodeAddressListener;
|
private ChangeListener<NodeAddress> connectionNodeAddressListener;
|
||||||
private Subscription networkReadySubscription;
|
private Subscription networkReadySubscription;
|
||||||
private boolean isBootstrapped;
|
private boolean isBootstrapped;
|
||||||
|
private ChangeListener<Number> numOfBroadcastsChangeListener;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -537,18 +538,35 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
|
||||||
log.debug("remove result=" + result);
|
log.debug("remove result=" + result);
|
||||||
sendMailboxMessageListener.onFault("A timeout occurred when trying to broadcast mailbox data.");
|
sendMailboxMessageListener.onFault("A timeout occurred when trying to broadcast mailbox data.");
|
||||||
}, 30);
|
}, 30);
|
||||||
broadcaster.addOneTimeListener(message -> {
|
Broadcaster.Listener listener = message -> {
|
||||||
if (message instanceof AddDataMessage &&
|
if (message instanceof AddDataMessage &&
|
||||||
((AddDataMessage) message).data.equals(protectedMailboxData)) {
|
((AddDataMessage) message).data.equals(protectedMailboxData)) {
|
||||||
sendMailboxMessageListener.onStoredInMailbox();
|
sendMailboxMessageListener.onStoredInMailbox();
|
||||||
sendMailboxMessageTimeoutTimer.cancel();
|
sendMailboxMessageTimeoutTimer.cancel();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
broadcaster.addListener(listener);
|
||||||
|
if (numOfBroadcastsChangeListener != null) {
|
||||||
|
log.warn("numOfBroadcastsChangeListener should be null");
|
||||||
|
broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener);
|
||||||
|
}
|
||||||
|
numOfBroadcastsChangeListener = (observable, oldValue, newValue) -> {
|
||||||
|
// We want to get at least 1 successful broadcast
|
||||||
|
if ((int) newValue > 0)
|
||||||
|
broadcaster.removeListener(listener);
|
||||||
|
|
||||||
|
UserThread.execute(() -> {
|
||||||
|
broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener);
|
||||||
|
numOfBroadcastsChangeListener = null;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
broadcaster.getNumOfBroadcastsProperty().addListener(numOfBroadcastsChangeListener);
|
||||||
|
|
||||||
boolean result = p2PDataStorage.add(protectedMailboxData, networkNode.getNodeAddress());
|
boolean result = p2PDataStorage.add(protectedMailboxData, networkNode.getNodeAddress());
|
||||||
if (!result) {
|
if (!result) {
|
||||||
sendMailboxMessageTimeoutTimer.cancel();
|
sendMailboxMessageTimeoutTimer.cancel();
|
||||||
|
broadcaster.removeListener(listener);
|
||||||
|
broadcaster.getNumOfBroadcastsProperty().removeListener(numOfBroadcastsChangeListener);
|
||||||
sendMailboxMessageListener.onFault("Data already exists in our local database");
|
sendMailboxMessageListener.onFault("Data already exists in our local database");
|
||||||
boolean result2 = p2PDataStorage.remove(protectedMailboxData, networkNode.getNodeAddress());
|
boolean result2 = p2PDataStorage.remove(protectedMailboxData, networkNode.getNodeAddress());
|
||||||
log.debug("remove result=" + result2);
|
log.debug("remove result=" + result2);
|
||||||
|
|
|
@ -3,7 +3,8 @@ package io.bitsquare.p2p.network;
|
||||||
public enum IllegalRequest {
|
public enum IllegalRequest {
|
||||||
MaxSizeExceeded(1),
|
MaxSizeExceeded(1),
|
||||||
InvalidDataType(0),
|
InvalidDataType(0),
|
||||||
WrongNetworkId(0);
|
WrongNetworkId(0),
|
||||||
|
TooManyMessages(1);
|
||||||
|
|
||||||
public final int maxTolerance;
|
public final int maxTolerance;
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,6 @@ public abstract class NetworkNode implements MessageListener, ConnectionListener
|
||||||
return outboundConnection;
|
return outboundConnection;
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
if (!(throwable instanceof ConnectException || throwable instanceof IOException)) {
|
if (!(throwable instanceof ConnectException || throwable instanceof IOException)) {
|
||||||
throwable.printStackTrace();
|
|
||||||
log.error("Executing task failed. " + throwable.getMessage());
|
log.error("Executing task failed. " + throwable.getMessage());
|
||||||
}
|
}
|
||||||
throw throwable;
|
throw throwable;
|
||||||
|
|
|
@ -8,6 +8,8 @@ import io.bitsquare.p2p.NodeAddress;
|
||||||
import io.bitsquare.p2p.network.Connection;
|
import io.bitsquare.p2p.network.Connection;
|
||||||
import io.bitsquare.p2p.network.NetworkNode;
|
import io.bitsquare.p2p.network.NetworkNode;
|
||||||
import io.bitsquare.p2p.storage.messages.DataBroadcastMessage;
|
import io.bitsquare.p2p.storage.messages.DataBroadcastMessage;
|
||||||
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -27,12 +29,16 @@ public class Broadcaster {
|
||||||
private final NetworkNode networkNode;
|
private final NetworkNode networkNode;
|
||||||
private final Set<Listener> listeners = new CopyOnWriteArraySet<>();
|
private final Set<Listener> listeners = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
|
||||||
|
private IntegerProperty numOfBroadcasts = new SimpleIntegerProperty(0);
|
||||||
|
|
||||||
public Broadcaster(NetworkNode networkNode) {
|
public Broadcaster(NetworkNode networkNode) {
|
||||||
this.networkNode = networkNode;
|
this.networkNode = networkNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(DataBroadcastMessage message, @Nullable NodeAddress sender) {
|
public void broadcast(DataBroadcastMessage message, @Nullable NodeAddress sender) {
|
||||||
Log.traceCall("Sender " + sender + ". Message " + message.toString());
|
Log.traceCall("Sender " + sender + ". Message " + message.toString());
|
||||||
|
numOfBroadcasts.set(0);
|
||||||
Set<Connection> receivers = networkNode.getConfirmedConnections();
|
Set<Connection> receivers = networkNode.getConfirmedConnections();
|
||||||
if (!receivers.isEmpty()) {
|
if (!receivers.isEmpty()) {
|
||||||
log.info("Broadcast message to {} peers. Message: {}", receivers.size(), message);
|
log.info("Broadcast message to {} peers. Message: {}", receivers.size(), message);
|
||||||
|
@ -46,9 +52,9 @@ public class Broadcaster {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Connection connection) {
|
public void onSuccess(Connection connection) {
|
||||||
log.trace("Broadcast to " + connection + " succeeded.");
|
log.trace("Broadcast to " + connection + " succeeded.");
|
||||||
|
numOfBroadcasts.set(numOfBroadcasts.get() + 1);
|
||||||
listeners.stream().forEach(listener -> {
|
listeners.stream().forEach(listener -> {
|
||||||
listener.onBroadcasted(message);
|
listener.onBroadcasted(message);
|
||||||
listeners.remove(listener);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +70,16 @@ public class Broadcaster {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IntegerProperty getNumOfBroadcastsProperty() {
|
||||||
|
return numOfBroadcasts;
|
||||||
|
}
|
||||||
|
|
||||||
// That listener gets immediately removed after the handler is called
|
// That listener gets immediately removed after the handler is called
|
||||||
public void addOneTimeListener(Listener listener) {
|
public void addListener(Listener listener) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeListener(Listener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,6 +253,7 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener
|
||||||
!peerManager.isConfirmed(e))
|
!peerManager.isConfirmed(e))
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
.stream()
|
.stream()
|
||||||
|
.filter(e -> e.lastActivityDate != null)
|
||||||
.sorted((o1, o2) -> o2.lastActivityDate.compareTo(o1.lastActivityDate))
|
.sorted((o1, o2) -> o2.lastActivityDate.compareTo(o1.lastActivityDate))
|
||||||
.map(e -> e.nodeAddress)
|
.map(e -> e.nodeAddress)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
|
@ -8,7 +8,6 @@ import io.bitsquare.p2p.network.*;
|
||||||
import io.bitsquare.p2p.peers.messages.data.UpdateDataRequest;
|
import io.bitsquare.p2p.peers.messages.data.UpdateDataRequest;
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -44,13 +43,13 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
|
|
||||||
private static final int MAX_REPORTED_PEERS = 1000;
|
private static final int MAX_REPORTED_PEERS = 1000;
|
||||||
private static final int MAX_PERSISTED_PEERS = 500;
|
private static final int MAX_PERSISTED_PEERS = 500;
|
||||||
private static final long MAX_AGE = 14 * 24 * 60 * 60 * 1000; // max age for reported peers is 14 days
|
private static final long DAY = 24 * 60 * 60 * 1000; // max age for reported peers is 14 days
|
||||||
|
private static final long MAX_AGE = 14 * DAY; // max age for reported peers is 14 days
|
||||||
|
|
||||||
|
|
||||||
private final NetworkNode networkNode;
|
private final NetworkNode networkNode;
|
||||||
private final Set<NodeAddress> seedNodeAddresses;
|
private final Set<NodeAddress> seedNodeAddresses;
|
||||||
@Nullable
|
private final Storage<HashSet<ReportedPeer>> dbStorage;
|
||||||
private Storage<HashSet<ReportedPeer>> dbStorage;
|
|
||||||
|
|
||||||
private final HashSet<ReportedPeer> persistedPeers = new HashSet<>();
|
private final HashSet<ReportedPeer> persistedPeers = new HashSet<>();
|
||||||
private final Set<ReportedPeer> reportedPeers = new HashSet<>();
|
private final Set<ReportedPeer> reportedPeers = new HashSet<>();
|
||||||
|
@ -66,7 +65,12 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
this.networkNode = networkNode;
|
this.networkNode = networkNode;
|
||||||
this.seedNodeAddresses = new HashSet<>(seedNodeAddresses);
|
this.seedNodeAddresses = new HashSet<>(seedNodeAddresses);
|
||||||
networkNode.addConnectionListener(this);
|
networkNode.addConnectionListener(this);
|
||||||
createDbStorage(storageDir);
|
dbStorage = new Storage<>(storageDir);
|
||||||
|
HashSet<ReportedPeer> persistedPeers = dbStorage.initAndGetPersisted("persistedPeers");
|
||||||
|
if (persistedPeers != null) {
|
||||||
|
log.info("We have persisted reported peers. persistedPeers.size()=" + persistedPeers.size());
|
||||||
|
this.persistedPeers.addAll(persistedPeers);
|
||||||
|
}
|
||||||
|
|
||||||
connectionNodeAddressListener = (observable, oldValue, newValue) -> {
|
connectionNodeAddressListener = (observable, oldValue, newValue) -> {
|
||||||
// Every time we get a new peer connected with a known address we check if we need to remove peers
|
// Every time we get a new peer connected with a known address we check if we need to remove peers
|
||||||
|
@ -79,21 +83,6 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createDbStorage(File storageDir) {
|
|
||||||
dbStorage = new Storage<>(storageDir);
|
|
||||||
initPersistedPeers();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initPersistedPeers() {
|
|
||||||
if (dbStorage != null) {
|
|
||||||
HashSet<ReportedPeer> persistedPeers = dbStorage.initAndGetPersisted("persistedPeers");
|
|
||||||
if (persistedPeers != null) {
|
|
||||||
log.info("We have persisted reported peers. persistedPeers.size()=" + persistedPeers.size());
|
|
||||||
this.persistedPeers.addAll(persistedPeers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shutDown() {
|
public void shutDown() {
|
||||||
Log.traceCall();
|
Log.traceCall();
|
||||||
|
|
||||||
|
@ -124,10 +113,15 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
public void onDisconnect(Reason reason, Connection connection) {
|
public void onDisconnect(Reason reason, Connection connection) {
|
||||||
connection.getNodeAddressProperty().removeListener(connectionNodeAddressListener);
|
connection.getNodeAddressProperty().removeListener(connectionNodeAddressListener);
|
||||||
connection.getPeersNodeAddressOptional().ifPresent(nodeAddress -> {
|
connection.getPeersNodeAddressOptional().ifPresent(nodeAddress -> {
|
||||||
ReportedPeer reportedPeer = new ReportedPeer(nodeAddress);
|
penalizeUnreachablePeer(nodeAddress);
|
||||||
|
Optional<ReportedPeer> reportedPeerOptional = reportedPeers.stream()
|
||||||
|
.filter(e -> e.nodeAddress.equals(nodeAddress)).findAny();
|
||||||
|
if (reportedPeerOptional.isPresent()) {
|
||||||
|
ReportedPeer reportedPeer = reportedPeerOptional.get();
|
||||||
reportedPeers.remove(reportedPeer);
|
reportedPeers.remove(reportedPeer);
|
||||||
persistedPeers.add(reportedPeer);
|
persistedPeers.add(reportedPeer);
|
||||||
dbStorage.queueUpForSave(persistedPeers, 5000);
|
dbStorage.queueUpForSave(persistedPeers, 5000);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,12 +209,14 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
|
|
||||||
private void removeTooOldReportedPeers() {
|
private void removeTooOldReportedPeers() {
|
||||||
Set<ReportedPeer> reportedPeersToRemove = reportedPeers.stream()
|
Set<ReportedPeer> reportedPeersToRemove = reportedPeers.stream()
|
||||||
.filter(reportedPeer -> new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
|
.filter(reportedPeer -> reportedPeer.lastActivityDate != null &&
|
||||||
|
new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
reportedPeersToRemove.forEach(this::removeReportedPeer);
|
reportedPeersToRemove.forEach(this::removeReportedPeer);
|
||||||
|
|
||||||
Set<ReportedPeer> persistedPeersToRemove = persistedPeers.stream()
|
Set<ReportedPeer> persistedPeersToRemove = persistedPeers.stream()
|
||||||
.filter(reportedPeer -> new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
|
.filter(reportedPeer -> reportedPeer.lastActivityDate != null &&
|
||||||
|
new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
persistedPeersToRemove.forEach(this::removeFromPersistedPeers);
|
persistedPeersToRemove.forEach(this::removeFromPersistedPeers);
|
||||||
}
|
}
|
||||||
|
@ -312,6 +308,7 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
if (toRemove2 > 0) {
|
if (toRemove2 > 0) {
|
||||||
// now we remove second half with a list sorted by oldest lastActivityDate
|
// now we remove second half with a list sorted by oldest lastActivityDate
|
||||||
list = new ArrayList<>(persistedPeers);
|
list = new ArrayList<>(persistedPeers);
|
||||||
|
list = list.stream().filter(e -> e.lastActivityDate != null).collect(Collectors.toList());
|
||||||
list.sort((o1, o2) -> o1.lastActivityDate.compareTo(o2.lastActivityDate));
|
list.sort((o1, o2) -> o1.lastActivityDate.compareTo(o2.lastActivityDate));
|
||||||
for (int i = 0; i < toRemove2; i++) {
|
for (int i = 0; i < toRemove2; i++) {
|
||||||
persistedPeers.remove(list.get(i));
|
persistedPeers.remove(list.get(i));
|
||||||
|
@ -330,10 +327,11 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
private void printReportedPeers() {
|
private void printReportedPeers() {
|
||||||
if (!reportedPeers.isEmpty()) {
|
if (!reportedPeers.isEmpty()) {
|
||||||
StringBuilder result = new StringBuilder("\n\n------------------------------------------------------------\n" +
|
StringBuilder result = new StringBuilder("\n\n------------------------------------------------------------\n" +
|
||||||
"Reported peers for node " + networkNode.getNodeAddress() + ":");
|
"Reported peers:");
|
||||||
reportedPeers.stream().forEach(e -> result.append("\n").append(e));
|
reportedPeers.stream().forEach(e -> result.append("\n").append(e));
|
||||||
result.append("\n------------------------------------------------------------\n");
|
result.append("\n------------------------------------------------------------\n");
|
||||||
log.info(result.toString());
|
log.debug(result.toString());
|
||||||
|
log.info("Number of reported peers: {}", reportedPeers.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,21 +370,16 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
reportedPeers.stream()
|
reportedPeers.stream()
|
||||||
.filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress))
|
.filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress))
|
||||||
.findAny()
|
.findAny()
|
||||||
.ifPresent(this::adjustLastActivityDate);
|
.ifPresent(ReportedPeer::penalizeLastActivityDate);
|
||||||
persistedPeers.stream()
|
persistedPeers.stream()
|
||||||
.filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress))
|
.filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress))
|
||||||
.findAny()
|
.findAny()
|
||||||
.ifPresent(reportedPeer -> {
|
.ifPresent(reportedPeer -> {
|
||||||
adjustLastActivityDate(reportedPeer);
|
reportedPeer.penalizeLastActivityDate();
|
||||||
dbStorage.queueUpForSave(persistedPeers, 5000);
|
dbStorage.queueUpForSave(persistedPeers, 5000);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
private void adjustLastActivityDate(ReportedPeer reportedPeer) {
|
removeTooOldReportedPeers();
|
||||||
long now = new Date().getTime();
|
|
||||||
long diff = now - reportedPeer.lastActivityDate.getTime();
|
|
||||||
long reduced = now - diff * 2;
|
|
||||||
reportedPeer.setLastActivityDate(new Date(reduced));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ReportedPeer> getConnectedAndReportedPeers() {
|
public Set<ReportedPeer> getConnectedAndReportedPeers() {
|
||||||
|
|
|
@ -18,12 +18,13 @@ public class ReportedPeer implements Serializable {
|
||||||
this.lastActivityDate = lastActivityDate;
|
this.lastActivityDate = lastActivityDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReportedPeer(NodeAddress nodeAddress) {
|
public void penalizeLastActivityDate() {
|
||||||
this(nodeAddress, null);
|
if (lastActivityDate != null) {
|
||||||
|
long now = new Date().getTime();
|
||||||
|
long diff = Math.max(24 * 60 * 60 * 1000, now - lastActivityDate.getTime());
|
||||||
|
long reduced = now - diff * 2;
|
||||||
|
lastActivityDate = new Date(reduced);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastActivityDate(Date lastActivityDate) {
|
|
||||||
this.lastActivityDate = lastActivityDate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't use the lastActivityDate for identity
|
// We don't use the lastActivityDate for identity
|
||||||
|
|
|
@ -233,6 +233,7 @@ public class RequestDataManager implements MessageListener {
|
||||||
!peerManager.isSelf(e))
|
!peerManager.isSelf(e))
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
.stream()
|
.stream()
|
||||||
|
.filter(e -> e.lastActivityDate != null)
|
||||||
.sorted((o1, o2) -> o2.lastActivityDate.compareTo(o1.lastActivityDate))
|
.sorted((o1, o2) -> o2.lastActivityDate.compareTo(o1.lastActivityDate))
|
||||||
.map(e -> e.nodeAddress)
|
.map(e -> e.nodeAddress)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
|
@ -161,7 +161,8 @@ public class P2PDataStorage implements MessageListener {
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n");
|
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n");
|
||||||
sb.append("Data set after addProtectedExpirableData (truncated)");
|
sb.append("Data set after addProtectedExpirableData (truncated)");
|
||||||
map.values().stream().forEach(e -> sb.append("\n").append(e.toString().substring(0, 40)).append("...\n"));
|
map.values().stream().forEach(e -> sb.append("\n").append(e.toString()
|
||||||
|
.substring(0, Math.min(50, e.toString().length()))).append("...\n"));
|
||||||
sb.append("\n------------------------------------------------------------\n");
|
sb.append("\n------------------------------------------------------------\n");
|
||||||
log.trace(sb.toString());
|
log.trace(sb.toString());
|
||||||
log.info("Data set after addProtectedExpirableData: size=" + map.values().size());
|
log.info("Data set after addProtectedExpirableData: size=" + map.values().size());
|
||||||
|
@ -280,7 +281,8 @@ public class P2PDataStorage implements MessageListener {
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n" +
|
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n" +
|
||||||
"Data set after removeProtectedExpirableData: (truncated)");
|
"Data set after removeProtectedExpirableData: (truncated)");
|
||||||
map.values().stream().forEach(e -> sb.append("\n").append(e.toString().substring(0, 40)).append("...\n"));
|
map.values().stream().forEach(e -> sb.append("\n").append(e.toString()
|
||||||
|
.substring(0, Math.min(50, e.toString().length()))).append("...\n"));
|
||||||
sb.append("\n------------------------------------------------------------\n");
|
sb.append("\n------------------------------------------------------------\n");
|
||||||
log.trace(sb.toString());
|
log.trace(sb.toString());
|
||||||
log.info("Data set after addProtectedExpirableData: size=" + map.values().size());
|
log.info("Data set after addProtectedExpirableData: size=" + map.values().size());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue