mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 15:00:30 +01:00
Merge branch 'Development' into dao
# Conflicts: # core/src/main/java/io/bisq/core/dao/blockchain/BsqNode.java
This commit is contained in:
commit
0e16522307
18 changed files with 135 additions and 74 deletions
|
@ -566,6 +566,7 @@ message Filter {
|
|||
repeated string seed_nodes = 10;
|
||||
repeated string price_relay_nodes = 11;
|
||||
bool prevent_public_btc_network = 12;
|
||||
repeated string btc_nodes = 13;
|
||||
}
|
||||
|
||||
// not used anymore from v0.6 on. But leave it for receiving TradeStatistics objects from older
|
||||
|
|
|
@ -1187,6 +1187,7 @@ filterWindow.bannedPaymentMethods=Filtered payment method IDs (comma sep.):
|
|||
filterWindow.arbitrators=Filtered arbitrators (comma sep. onion addresses):
|
||||
filterWindow.seedNode=Filtered seed nodes (comma sep. onion addresses):
|
||||
filterWindow.priceRelayNode=Filtered price relay nodes (comma sep. onion addresses):
|
||||
filterWindow.btcNode=Filtered Bitcoin nodes (comma sep. addresses + port):
|
||||
filterWindow.preventPublicBtcNetwork=Prevent usage of public Bitcoin network:
|
||||
filterWindow.add=Add filter
|
||||
filterWindow.remove=Remove filter
|
||||
|
|
|
@ -175,9 +175,7 @@ public class BisqEnvironment extends StandardEnvironment {
|
|||
@Setter
|
||||
private boolean isBitcoinLocalhostNodeRunning;
|
||||
@Getter
|
||||
private List<String> bannedPriceRelayNodes;
|
||||
@Getter
|
||||
private List<String> bannedSeedNodes;
|
||||
private List<String> bannedSeedNodes, bannedBtcNodes, bannedPriceRelayNodes;
|
||||
|
||||
private final String btcNodes, seedNodes, ignoreDevMsg, useTorForBtc, rpcUser, rpcPassword,
|
||||
rpcPort, rpcBlockNotificationPort, dumpBlockchainData, fullDaoNode,
|
||||
|
@ -281,6 +279,9 @@ public class BisqEnvironment extends StandardEnvironment {
|
|||
final String bannedSeedNodesAsString = getProperty(FilterManager.BANNED_SEED_NODES, "");
|
||||
bannedSeedNodes = !bannedSeedNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedSeedNodesAsString).split(",")) : null;
|
||||
|
||||
final String bannedBtcNodesAsString = getProperty(FilterManager.BANNED_BTC_NODES, "");
|
||||
bannedBtcNodes = !bannedBtcNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedBtcNodesAsString).split(",")) : null;
|
||||
|
||||
baseCurrencyNetwork = BaseCurrencyNetwork.valueOf(getProperty(BtcOptionKeys.BASE_CURRENCY_NETWORK,
|
||||
getDefaultBaseCurrencyNetwork().name()).toUpperCase());
|
||||
|
||||
|
@ -306,6 +307,10 @@ public class BisqEnvironment extends StandardEnvironment {
|
|||
setProperty(FilterManager.BANNED_SEED_NODES, bannedNodes == null ? "" : String.join(",", bannedNodes));
|
||||
}
|
||||
|
||||
public void saveBannedBtcNodes(@Nullable List<String> bannedNodes) {
|
||||
setProperty(FilterManager.BANNED_BTC_NODES, bannedNodes == null ? "" : String.join(",", bannedNodes));
|
||||
}
|
||||
|
||||
public void saveBannedPriceRelayNodes(@Nullable List<String> bannedNodes) {
|
||||
setProperty(FilterManager.BANNED_PRICE_RELAY_NODES, bannedNodes == null ? "" : String.join(",", bannedNodes));
|
||||
}
|
||||
|
|
|
@ -20,44 +20,67 @@ package io.bisq.core.btc;
|
|||
import io.bisq.core.app.BisqEnvironment;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
// Managed here: https://github.com/bisq-network/roles/issues/39
|
||||
@Slf4j
|
||||
public class BitcoinNodes {
|
||||
|
||||
private final List<String> bannedNodes;
|
||||
|
||||
public enum BitcoinNodesOption {
|
||||
PROVIDED,
|
||||
CUSTOM,
|
||||
PUBLIC
|
||||
}
|
||||
|
||||
@Inject
|
||||
public BitcoinNodes(BisqEnvironment bisqEnvironment) {
|
||||
bannedNodes = bisqEnvironment.getBannedBtcNodes();
|
||||
}
|
||||
|
||||
// For other base currencies or testnet we ignore provided nodes
|
||||
public List<BtcNode> getProvidedBtcNodes() {
|
||||
return useProvidedBtcNodes() ?
|
||||
Arrays.asList(
|
||||
public Set<BtcNode> getProvidedBtcNodes() {
|
||||
Set<BtcNode> btcNodes = useProvidedBtcNodes() ?
|
||||
new HashSet<>(Arrays.asList(
|
||||
BtcNode.fromHostNameAddressAndPort("kirsche.emzy.de", "78.47.61.83", BtcNode.DEFAULT_PORT, "https://github.com/emzy"),
|
||||
BtcNode.fromOnion("poyvpdt762gllauu.onion", BtcNode.DEFAULT_PORT, "https://github.com/emzy"),
|
||||
BtcNode.fromHostName("poyvpdt762gllauu.onion", BtcNode.DEFAULT_PORT, "https://github.com/emzy"),
|
||||
BtcNode.fromHostNameAndAddress("bitcoin.christophatteneder.com", "174.138.35.229", "https://github.com/ripcurlx"),
|
||||
BtcNode.fromOnion("r3dsojfhwcm7x7p6.onion", BtcNode.DEFAULT_PORT, "https://github.com/emzy"),
|
||||
BtcNode.fromOnion("vlf5i3grro3wux24.onion", BtcNode.DEFAULT_PORT, "https://github.com/alexej996"),
|
||||
BtcNode.fromOnion("3r44ddzjitznyahw.onion", BtcNode.DEFAULT_PORT, "https://github.com/sqrrm"),
|
||||
BtcNode.fromOnion("i3a5xtzfm4xwtybd.onion", BtcNode.DEFAULT_PORT, "https://github.com/sqrrm"),
|
||||
BtcNode.fromHostName("r3dsojfhwcm7x7p6.onion", BtcNode.DEFAULT_PORT, "https://github.com/emzy"),
|
||||
BtcNode.fromHostName("vlf5i3grro3wux24.onion", BtcNode.DEFAULT_PORT, "https://github.com/alexej996"),
|
||||
BtcNode.fromHostName("3r44ddzjitznyahw.onion", BtcNode.DEFAULT_PORT, "https://github.com/sqrrm"),
|
||||
BtcNode.fromHostName("i3a5xtzfm4xwtybd.onion", BtcNode.DEFAULT_PORT, "https://github.com/sqrrm"),
|
||||
BtcNode.fromHostNameAddressAndPort("bitcoin4-fullnode.csg.uzh.ch", "192.41.136.217", BtcNode.DEFAULT_PORT, "https://github.com/tbocek"),
|
||||
BtcNode.fromHostNameAddressAndPort("bcwat.ch", "5.189.166.193", BtcNode.DEFAULT_PORT, "https://github.com/sgeisler"),
|
||||
BtcNode.fromHostNameAddressAndPort("btc.jochen-hoenicke.de", "37.221.198.57", BtcNode.DEFAULT_PORT, "https://github.com/jhoenicke"), //
|
||||
BtcNode.fromHostNameAddressAndPort("btc.vante.me", "138.68.117.247", BtcNode.DEFAULT_PORT, "https://github.com/mrosseel"),
|
||||
BtcNode.fromOnion("mxdtrjhe2yfsx3pg.onion", BtcNode.DEFAULT_PORT, "https://github.com/mrosseel"),
|
||||
BtcNode.fromHostName("mxdtrjhe2yfsx3pg.onion", BtcNode.DEFAULT_PORT, "https://github.com/mrosseel"),
|
||||
BtcNode.fromAddressAndPort("62.75.210.81", BtcNode.DEFAULT_PORT, "https://github.com/emzy"),
|
||||
BtcNode.fromAddressAndPort("163.172.171.119", BtcNode.DEFAULT_PORT, "https://github.com/emzy")
|
||||
) :
|
||||
new ArrayList<>();
|
||||
)) :
|
||||
new HashSet<>();
|
||||
|
||||
btcNodes = btcNodes.stream()
|
||||
.filter(e -> bannedNodes == null || !bannedNodes.contains(e.getAddressOrHostWithPort()))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (bannedNodes == null)
|
||||
log.info("btcNodes={}", btcNodes);
|
||||
else
|
||||
log.warn("We received banned btc nodes={}, btcNodes={}", bannedNodes, btcNodes);
|
||||
|
||||
return btcNodes;
|
||||
}
|
||||
|
||||
public boolean useProvidedBtcNodes() {
|
||||
|
@ -85,14 +108,14 @@ public class BitcoinNodes {
|
|||
String[] parts = fullAddress.split(":");
|
||||
checkArgument(parts.length > 0);
|
||||
if (parts.length == 1) {
|
||||
return BtcNode.fromOnion(parts[0], DEFAULT_PORT, null);
|
||||
return BtcNode.fromHostName(parts[0], DEFAULT_PORT, null);
|
||||
} else {
|
||||
checkArgument(parts.length == 2);
|
||||
return BtcNode.fromHostNameAndPort(parts[0], Integer.valueOf(parts[1]), null);
|
||||
}
|
||||
}
|
||||
|
||||
public static BtcNode fromOnion(String hostName, int port, @Nullable String operator) {
|
||||
public static BtcNode fromHostName(String hostName, int port, @Nullable String operator) {
|
||||
return new BtcNode(hostName, null, port, operator);
|
||||
}
|
||||
|
||||
|
@ -149,5 +172,10 @@ public class BitcoinNodes {
|
|||
else
|
||||
return hostName;
|
||||
}
|
||||
|
||||
public String getAddressOrHostWithPort() {
|
||||
log.error(getHostAddressOrHostName() + ":" + port);
|
||||
return getHostAddressOrHostName() + ":" + port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,10 +57,7 @@ import java.net.InetAddress;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -269,17 +266,17 @@ public class WalletsSetup {
|
|||
walletConfig.connectToLocalHost();
|
||||
}
|
||||
} else {
|
||||
List<BitcoinNodes.BtcNode> btcNodeList = new ArrayList<>();
|
||||
Set<BitcoinNodes.BtcNode> btcNodes = new HashSet<>();
|
||||
switch (BitcoinNodes.BitcoinNodesOption.values()[preferences.getBitcoinNodesOptionOrdinal()]) {
|
||||
case CUSTOM:
|
||||
String bitcoinNodesString = preferences.getBitcoinNodes();
|
||||
if (bitcoinNodesString != null) {
|
||||
btcNodeList = Splitter.on(",")
|
||||
btcNodes = Splitter.on(",")
|
||||
.splitToList(StringUtils.deleteWhitespace(bitcoinNodesString))
|
||||
.stream()
|
||||
.filter(e -> !e.isEmpty())
|
||||
.map(BitcoinNodes.BtcNode::fromFullAddress)
|
||||
.collect(Collectors.toList());
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
break;
|
||||
case PUBLIC:
|
||||
|
@ -287,13 +284,13 @@ public class WalletsSetup {
|
|||
break;
|
||||
default:
|
||||
case PROVIDED:
|
||||
btcNodeList = bitcoinNodes.getProvidedBtcNodes();
|
||||
btcNodes = bitcoinNodes.getProvidedBtcNodes();
|
||||
break;
|
||||
}
|
||||
|
||||
final boolean useTorForBitcoinJ = socks5Proxy != null;
|
||||
List<PeerAddress> peerAddressList = new ArrayList<>();
|
||||
btcNodeList.forEach(btcNode -> {
|
||||
btcNodes.forEach(btcNode -> {
|
||||
if (useTorForBitcoinJ) {
|
||||
if (btcNode.isHiddenService()) {
|
||||
// no DNS lookup for onion addresses
|
||||
|
|
|
@ -53,7 +53,7 @@ public final class Filter implements ProtectedStoragePayload {
|
|||
@Nullable
|
||||
private final List<String> bannedPaymentMethods;
|
||||
|
||||
// added in v0.6
|
||||
// added in v0.6.0
|
||||
@Nullable
|
||||
private final List<String> arbitrators;
|
||||
@Nullable
|
||||
|
@ -62,6 +62,11 @@ public final class Filter implements ProtectedStoragePayload {
|
|||
private final List<String> priceRelayNodes;
|
||||
private final boolean preventPublicBtcNetwork;
|
||||
|
||||
// added in v0.6.2
|
||||
@Nullable
|
||||
private final List<String> btcNodes;
|
||||
|
||||
|
||||
private String signatureAsBase64;
|
||||
private byte[] ownerPubKeyBytes;
|
||||
// Should be only used in emergency case if we need to add data but do not want to break backward compatibility
|
||||
|
@ -79,7 +84,8 @@ public final class Filter implements ProtectedStoragePayload {
|
|||
@Nullable List<String> arbitrators,
|
||||
@Nullable List<String> seedNodes,
|
||||
@Nullable List<String> priceRelayNodes,
|
||||
boolean preventPublicBtcNetwork) {
|
||||
boolean preventPublicBtcNetwork,
|
||||
@Nullable List<String> btcNodes) {
|
||||
this.bannedOfferIds = bannedOfferIds;
|
||||
this.bannedNodeAddress = bannedNodeAddress;
|
||||
this.bannedPaymentAccounts = bannedPaymentAccounts;
|
||||
|
@ -89,6 +95,7 @@ public final class Filter implements ProtectedStoragePayload {
|
|||
this.seedNodes = seedNodes;
|
||||
this.priceRelayNodes = priceRelayNodes;
|
||||
this.preventPublicBtcNetwork = preventPublicBtcNetwork;
|
||||
this.btcNodes = btcNodes;
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,6 +113,7 @@ public final class Filter implements ProtectedStoragePayload {
|
|||
@Nullable List<String> seedNodes,
|
||||
@Nullable List<String> priceRelayNodes,
|
||||
boolean preventPublicBtcNetwork,
|
||||
@Nullable List<String> btcNodes,
|
||||
String signatureAsBase64,
|
||||
byte[] ownerPubKeyBytes,
|
||||
@Nullable Map<String, String> extraDataMap) {
|
||||
|
@ -117,7 +125,8 @@ public final class Filter implements ProtectedStoragePayload {
|
|||
arbitrators,
|
||||
seedNodes,
|
||||
priceRelayNodes,
|
||||
preventPublicBtcNetwork);
|
||||
preventPublicBtcNetwork,
|
||||
btcNodes);
|
||||
this.signatureAsBase64 = signatureAsBase64;
|
||||
this.ownerPubKeyBytes = ownerPubKeyBytes;
|
||||
this.extraDataMap = extraDataMap;
|
||||
|
@ -145,6 +154,7 @@ public final class Filter implements ProtectedStoragePayload {
|
|||
Optional.ofNullable(arbitrators).ifPresent(builder::addAllArbitrators);
|
||||
Optional.ofNullable(seedNodes).ifPresent(builder::addAllSeedNodes);
|
||||
Optional.ofNullable(priceRelayNodes).ifPresent(builder::addAllPriceRelayNodes);
|
||||
Optional.ofNullable(btcNodes).ifPresent(builder::addAllBtcNodes);
|
||||
Optional.ofNullable(extraDataMap).ifPresent(builder::putAllExtraData);
|
||||
|
||||
return PB.StoragePayload.newBuilder().setFilter(builder).build();
|
||||
|
@ -162,6 +172,7 @@ public final class Filter implements ProtectedStoragePayload {
|
|||
CollectionUtils.isEmpty(proto.getSeedNodesList()) ? null : proto.getSeedNodesList().stream().collect(Collectors.toList()),
|
||||
CollectionUtils.isEmpty(proto.getPriceRelayNodesList()) ? null : proto.getPriceRelayNodesList().stream().collect(Collectors.toList()),
|
||||
proto.getPreventPublicBtcNetwork(),
|
||||
CollectionUtils.isEmpty(proto.getBtcNodesList()) ? null : proto.getBtcNodesList().stream().collect(Collectors.toList()),
|
||||
proto.getSignatureAsBase64(),
|
||||
proto.getOwnerPubKeyBytes().toByteArray(),
|
||||
CollectionUtils.isEmpty(proto.getExtraDataMap()) ? null : proto.getExtraDataMap());
|
||||
|
|
|
@ -58,6 +58,7 @@ public class FilterManager {
|
|||
|
||||
public static final String BANNED_PRICE_RELAY_NODES = "bannedPriceRelayNodes";
|
||||
public static final String BANNED_SEED_NODES = "bannedSeedNodes";
|
||||
public static final String BANNED_BTC_NODES = "bannedBtcNodes";
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -131,7 +132,7 @@ public class FilterManager {
|
|||
Filter filter = (Filter) data.getProtectedStoragePayload();
|
||||
if (verifySignature(filter)) {
|
||||
bisqEnvironment.saveBannedSeedNodes(null);
|
||||
|
||||
bisqEnvironment.saveBannedBtcNodes(null);
|
||||
bisqEnvironment.saveBannedPriceRelayNodes(null);
|
||||
providersRepository.applyBannedNodes(null);
|
||||
providersRepository.selectNewRandomBaseUrl();
|
||||
|
@ -150,6 +151,7 @@ public class FilterManager {
|
|||
// nodes at the next startup and don't update the list in the P2P network domain.
|
||||
// We persist it to the property file which is read before any other initialisation.
|
||||
bisqEnvironment.saveBannedSeedNodes(filter.getSeedNodes());
|
||||
bisqEnvironment.saveBannedBtcNodes(filter.getBtcNodes());
|
||||
|
||||
// Banned price relay nodes we can apply at runtime
|
||||
final List<String> priceRelayNodes = filter.getPriceRelayNodes();
|
||||
|
|
|
@ -37,6 +37,8 @@ public class ProvidersRepository {
|
|||
"http://ceaanhbvluug4we6.onion/, " +// @mrosseel
|
||||
"http://rb2l2qale2pqzjyo.onion/"; // @sqrrm
|
||||
|
||||
// Old nodes before v 0.6.0: "http://44mgyoe2b6oqiytt.onion/, http://5bmpx76qllutpcyp.onion/"; @ManfredKarrer
|
||||
|
||||
private final String providersFromProgramArgs;
|
||||
private final boolean useLocalhostForP2P;
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ public class PriceFeedService {
|
|||
}
|
||||
|
||||
} else {
|
||||
String errorMessage = "We don't have a price for " + currencyCode;
|
||||
String errorMessage = "We don't have a price for " + currencyCode + ". priceProvider=" + priceProvider;
|
||||
log.debug(errorMessage);
|
||||
faultHandler.handleFault(errorMessage, new PriceRequestException(errorMessage));
|
||||
}
|
||||
|
@ -307,6 +307,7 @@ public class PriceFeedService {
|
|||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable throwable) {
|
||||
log.error("Could not load marketPrices. Error: " + throwable.toString());
|
||||
UserThread.execute(() -> faultHandler.handleFault("Could not load marketPrices", throwable));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -67,9 +67,4 @@ public class PriceProvider extends HttpClientProvider {
|
|||
});
|
||||
return new Tuple2<>(tsMap, marketPriceMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PriceProvider";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,13 +26,10 @@ import org.junit.Ignore;
|
|||
*/
|
||||
@SuppressWarnings("UnusedAssignment")
|
||||
public class UserPayloadModelVOTest {
|
||||
|
||||
|
||||
@Ignore("TODO InvalidKeySpecException at io.bisq.common.crypto.Sig.getPublicKeyFromBytes(Sig.java:135)")
|
||||
public void testRoundtrip() {
|
||||
UserPayload vo = new UserPayload();
|
||||
vo.setAccountId("accountId");
|
||||
|
||||
UserPayload newVo = UserPayload.fromProto(vo.toProtoMessage().getUserPayload(), new CoreProtoResolver());
|
||||
}
|
||||
|
||||
|
@ -43,7 +40,7 @@ public class UserPayloadModelVOTest {
|
|||
vo.setDisplayedAlert(new Alert("message", true, "version", new byte[]{12, -64, 12}, "string", null));
|
||||
vo.setDevelopersFilter(new Filter(Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(),
|
||||
Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(),
|
||||
false, "string", new byte[]{10, 0, 0}, null));
|
||||
false, Lists.newArrayList(), "string", new byte[]{10, 0, 0}, null));
|
||||
vo.setRegisteredArbitrator(ArbitratorTest.getArbitratorMock());
|
||||
vo.setRegisteredMediator(MediatorTest.getMediatorMock());
|
||||
vo.setAcceptedArbitrators(Lists.newArrayList(ArbitratorTest.getArbitratorMock()));
|
||||
|
|
|
@ -127,6 +127,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
|
|||
InputTextField arbitratorsInputTextField = addLabelInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.arbitrators")).second;
|
||||
InputTextField seedNodesInputTextField = addLabelInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.seedNode")).second;
|
||||
InputTextField priceRelayNodesInputTextField = addLabelInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.priceRelayNode")).second;
|
||||
InputTextField btcNodesInputTextField = addLabelInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.btcNode")).second;
|
||||
CheckBox preventPublicBtcNetworkCheckBox = addLabelCheckBox(gridPane, ++rowIndex, Res.get("filterWindow.preventPublicBtcNetwork")).second;
|
||||
// TODO add BTC full nodes
|
||||
|
||||
|
@ -164,6 +165,9 @@ public class FilterWindow extends Overlay<FilterWindow> {
|
|||
if (filter.getPriceRelayNodes() != null)
|
||||
priceRelayNodesInputTextField.setText(filter.getPriceRelayNodes().stream().collect(Collectors.joining(", ")));
|
||||
|
||||
if (filter.getBtcNodes() != null)
|
||||
btcNodesInputTextField.setText(filter.getBtcNodes().stream().collect(Collectors.joining(", ")));
|
||||
|
||||
preventPublicBtcNetworkCheckBox.setSelected(filter.isPreventPublicBtcNetwork());
|
||||
|
||||
}
|
||||
|
@ -177,6 +181,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
|
|||
List<String> arbitrators = new ArrayList<>();
|
||||
List<String> seedNodes = new ArrayList<>();
|
||||
List<String> priceRelayNodes = new ArrayList<>();
|
||||
List<String> btcNodes = new ArrayList<>();
|
||||
|
||||
if (!offerIdsInputTextField.getText().isEmpty()) {
|
||||
offerIds = new ArrayList<>(Arrays.asList(StringUtils.deleteWhitespace(offerIdsInputTextField.getText())
|
||||
|
@ -235,6 +240,11 @@ public class FilterWindow extends Overlay<FilterWindow> {
|
|||
.split(",")));
|
||||
}
|
||||
|
||||
if (!btcNodesInputTextField.getText().isEmpty()) {
|
||||
btcNodes = new ArrayList<>(Arrays.asList(StringUtils.deleteWhitespace(btcNodesInputTextField.getText())
|
||||
.split(",")));
|
||||
}
|
||||
|
||||
if (sendFilterMessageHandler.handle(new Filter(offerIds,
|
||||
nodes,
|
||||
paymentAccountFilters,
|
||||
|
@ -243,7 +253,8 @@ public class FilterWindow extends Overlay<FilterWindow> {
|
|||
arbitrators,
|
||||
seedNodes,
|
||||
priceRelayNodes,
|
||||
preventPublicBtcNetworkCheckBox.isSelected()),
|
||||
preventPublicBtcNetworkCheckBox.isSelected(),
|
||||
btcNodes),
|
||||
keyInputTextField.getText()))
|
||||
hide();
|
||||
else
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.bisq.common.app.Version;
|
|||
import io.bisq.common.util.Utilities;
|
||||
import io.bisq.network.http.HttpException;
|
||||
import io.bisq.provider.fee.FeeRequestService;
|
||||
import io.bisq.provider.fee.providers.BtcFeesProvider;
|
||||
import io.bisq.provider.price.PriceRequestService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -34,6 +35,7 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.security.NoSuchProviderException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static spark.Spark.get;
|
||||
import static spark.Spark.port;
|
||||
|
@ -59,20 +61,20 @@ public class ProviderMain {
|
|||
", P2P_NETWORK_VERSION=" + Version.P2P_NETWORK_VERSION +
|
||||
", LOCAL_DB_VERSION=" + Version.LOCAL_DB_VERSION +
|
||||
", TRADE_PROTOCOL_VERSION=" + Version.TRADE_PROTOCOL_VERSION +
|
||||
", BASE_CURRENCY_NETWORK=NOT SET" +
|
||||
", getP2PNetworkId()=NOT SET" +
|
||||
", BASE_CURRENCY_NETWORK=NOT SET" +
|
||||
", getP2PNetworkId()=NOT SET" +
|
||||
'}');
|
||||
Utilities.printSysInfo();
|
||||
|
||||
port(8080);
|
||||
|
||||
handleGetAllMarketPrices(args);
|
||||
handleGetFees();
|
||||
handleGetFees(args);
|
||||
handleGetVersion();
|
||||
}
|
||||
|
||||
private static void handleGetAllMarketPrices(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
|
||||
if (args.length == 2) {
|
||||
if (args.length >= 2) {
|
||||
String bitcoinAveragePrivKey = args[0];
|
||||
String bitcoinAveragePubKey = args[1];
|
||||
|
||||
|
@ -86,8 +88,19 @@ public class ProviderMain {
|
|||
}
|
||||
}
|
||||
|
||||
private static void handleGetFees() throws IOException {
|
||||
FeeRequestService feeRequestService = new FeeRequestService();
|
||||
private static void handleGetFees(String[] args) throws IOException {
|
||||
int capacity = BtcFeesProvider.CAPACITY;
|
||||
int maxBlocks = BtcFeesProvider.MAX_BLOCKS;
|
||||
if (args.length >= 4) {
|
||||
capacity = Integer.valueOf(args[2]);
|
||||
maxBlocks = Integer.valueOf(args[3]);
|
||||
}
|
||||
|
||||
long requestIntervalInMs = TimeUnit.MINUTES.toMillis(FeeRequestService.REQUEST_INTERVAL_MIN);
|
||||
if (args.length >= 5)
|
||||
requestIntervalInMs = TimeUnit.MINUTES.toMillis(Long.valueOf(args[4]));
|
||||
|
||||
FeeRequestService feeRequestService = new FeeRequestService(capacity, maxBlocks, requestIntervalInMs);
|
||||
get("/getFees", (req, res) -> {
|
||||
log.info("Incoming getFees request from: " + req.userAgent());
|
||||
return feeRequestService.getJson();
|
||||
|
|
|
@ -18,5 +18,5 @@
|
|||
package io.bisq.provider;
|
||||
|
||||
public class ProviderVersion {
|
||||
public static final String VERSION = "0.6.1";
|
||||
public static final String VERSION = "0.6.2";
|
||||
}
|
||||
|
|
|
@ -20,8 +20,7 @@ package io.bisq.provider.fee;
|
|||
import io.bisq.common.util.Utilities;
|
||||
import io.bisq.core.provider.fee.FeeService;
|
||||
import io.bisq.provider.fee.providers.BtcFeesProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
|
@ -30,13 +29,10 @@ import java.util.Map;
|
|||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
//TODO use protobuffer instead of json
|
||||
@Slf4j
|
||||
public class FeeRequestService {
|
||||
private static final Logger log = LoggerFactory.getLogger(FeeRequestService.class);
|
||||
|
||||
private static final long INTERVAL_BTC_FEES_MS = TimeUnit.MINUTES.toMillis(5);
|
||||
public static int REQUEST_INTERVAL_MIN = 5;
|
||||
|
||||
public static final long BTC_MIN_TX_FEE = 10; // satoshi/byte
|
||||
public static final long BTC_MAX_TX_FEE = 1000;
|
||||
|
@ -48,8 +44,8 @@ public class FeeRequestService {
|
|||
private long bitcoinFeesTs;
|
||||
private String json;
|
||||
|
||||
public FeeRequestService() throws IOException {
|
||||
btcFeesProvider = new BtcFeesProvider();
|
||||
public FeeRequestService(int capacity, int maxBlocks, long requestIntervalInMs) throws IOException {
|
||||
btcFeesProvider = new BtcFeesProvider(capacity, maxBlocks);
|
||||
|
||||
// For now we don't need a fee estimation for LTC so we set it fixed, but we keep it in the provider to
|
||||
// be flexible if fee pressure grows on LTC
|
||||
|
@ -58,10 +54,10 @@ public class FeeRequestService {
|
|||
dataMap.put("dashTxFee", FeeService.DASH_DEFAULT_TX_FEE);
|
||||
|
||||
writeToJson();
|
||||
startRequests();
|
||||
startRequests(requestIntervalInMs);
|
||||
}
|
||||
|
||||
private void startRequests() throws IOException {
|
||||
private void startRequests(long requestIntervalInMs) throws IOException {
|
||||
timerBitcoinFeesLocal.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -72,7 +68,7 @@ public class FeeRequestService {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, INTERVAL_BTC_FEES_MS, INTERVAL_BTC_FEES_MS);
|
||||
}, requestIntervalInMs, requestIntervalInMs);
|
||||
|
||||
|
||||
requestBitcoinFees();
|
||||
|
|
|
@ -14,14 +14,18 @@ import java.util.LinkedList;
|
|||
//TODO consider alternative https://www.bitgo.com/api/v1/tx/fee?numBlocks=3
|
||||
@Slf4j
|
||||
public class BtcFeesProvider {
|
||||
static int CAPACITY = 6; // we request each 5 min. so we take average of last 30 min.
|
||||
static int MAX_BLOCKS = 15;
|
||||
public static int CAPACITY = 4; // if we request each 5 min. we take average of last 20 min.
|
||||
public static int MAX_BLOCKS = 10;
|
||||
|
||||
private final HttpClient httpClient;
|
||||
LinkedList<Long> fees = new LinkedList<>();
|
||||
private final int capacity;
|
||||
private final int maxBlocks;
|
||||
|
||||
// other: https://estimatefee.com/n/2
|
||||
public BtcFeesProvider() {
|
||||
public BtcFeesProvider(int capacity, int maxBlocks) {
|
||||
this.capacity = capacity;
|
||||
this.maxBlocks = maxBlocks;
|
||||
this.httpClient = new HttpClient("https://bitcoinfees.earn.com/api/v1/fees/");
|
||||
}
|
||||
|
||||
|
@ -41,7 +45,7 @@ public class BtcFeesProvider {
|
|||
.flatMap(e -> e.getValue().stream())
|
||||
.forEach(e -> {
|
||||
Double maxDelay = e.get("maxDelay");
|
||||
if (maxDelay <= MAX_BLOCKS && fee[0] == 0)
|
||||
if (maxDelay <= maxBlocks && fee[0] == 0)
|
||||
fee[0] = MathUtils.roundDoubleToLong(e.get("maxFee"));
|
||||
});
|
||||
fee[0] = Math.min(Math.max(fee[0], FeeRequestService.BTC_MIN_TX_FEE), FeeRequestService.BTC_MAX_TX_FEE);
|
||||
|
@ -56,7 +60,7 @@ public class BtcFeesProvider {
|
|||
fees.add(newFee);
|
||||
long average = ((Double) fees.stream().mapToDouble(e -> e).average().getAsDouble()).longValue();
|
||||
log.info("average of last {} calls: {}", fees.size(), average);
|
||||
if (fees.size() == CAPACITY)
|
||||
if (fees.size() == capacity)
|
||||
fees.removeFirst();
|
||||
|
||||
return average;
|
||||
|
|
|
@ -84,10 +84,7 @@ public class PriceRequestService {
|
|||
public void run() {
|
||||
try {
|
||||
requestBtcAverageLocalPrices();
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
} catch (Throwable e) {
|
||||
log.warn(e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -25,23 +25,23 @@ public class BtcFeesProviderTest {
|
|||
|
||||
@Test
|
||||
public void testGetAverage() {
|
||||
BtcFeesProvider btcFeesProvider = new BtcFeesProvider();
|
||||
BtcFeesProvider btcFeesProvider = new BtcFeesProvider(BtcFeesProvider.CAPACITY, BtcFeesProvider.MAX_BLOCKS);
|
||||
|
||||
assertEquals(0, btcFeesProvider.getAverage(0));
|
||||
|
||||
btcFeesProvider = new BtcFeesProvider();
|
||||
btcFeesProvider = new BtcFeesProvider(BtcFeesProvider.CAPACITY, BtcFeesProvider.MAX_BLOCKS);
|
||||
assertEquals(1, btcFeesProvider.getAverage(1));
|
||||
|
||||
btcFeesProvider = new BtcFeesProvider();
|
||||
btcFeesProvider = new BtcFeesProvider(BtcFeesProvider.CAPACITY, BtcFeesProvider.MAX_BLOCKS);
|
||||
assertEquals(0, btcFeesProvider.getAverage(0));
|
||||
assertEquals(0, btcFeesProvider.getAverage(1));
|
||||
|
||||
btcFeesProvider = new BtcFeesProvider();
|
||||
btcFeesProvider = new BtcFeesProvider(BtcFeesProvider.CAPACITY, BtcFeesProvider.MAX_BLOCKS);
|
||||
assertEquals(0, btcFeesProvider.getAverage(0));
|
||||
assertEquals(1, btcFeesProvider.getAverage(2));
|
||||
|
||||
BtcFeesProvider.CAPACITY = 5;
|
||||
btcFeesProvider = new BtcFeesProvider();
|
||||
btcFeesProvider = new BtcFeesProvider(BtcFeesProvider.CAPACITY, BtcFeesProvider.MAX_BLOCKS);
|
||||
assertEquals(10, btcFeesProvider.getAverage(10));
|
||||
assertEquals(15, btcFeesProvider.getAverage(20));
|
||||
assertEquals(20, btcFeesProvider.getAverage(30));
|
||||
|
|
Loading…
Add table
Reference in a new issue