remove dependency on local BTC node

Co-authored-by: premek <1145361+premek@users.noreply.github.com>
This commit is contained in:
woodser 2022-01-05 20:18:25 -05:00
parent 1b78be689a
commit 9059974725
13 changed files with 143 additions and 161 deletions

View File

@ -12,7 +12,7 @@ localnet:
mkdir -p .localnet
nodes: localnet
./scripts/xmr_btc_deps.sh
./scripts/haveno_deps.sh
haveno:
./gradlew build

View File

@ -117,7 +117,7 @@ public class Config {
// Default values for certain options
public static final int UNSPECIFIED_PORT = -1;
public static final String DEFAULT_REGTEST_HOST = "localhost";
public static final String DEFAULT_REGTEST_HOST = "none";
public static final int DEFAULT_NUM_CONNECTIONS_FOR_BTC = 9; // down from BitcoinJ default of 12
static final String DEFAULT_CONFIG_FILE_NAME = "bisq.properties";

View File

@ -85,6 +85,7 @@ public class AppStartupState {
p2pNetworkAndWalletInitialized.subscribe((observable, oldValue, newValue) -> {
if (newValue) {
applicationFullyInitialized.set(true);
log.info("Application fully initialized");
}
});
}

View File

@ -0,0 +1,25 @@
package bisq.core.btc.setup;
import bisq.common.UserThread;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import java.util.Date;
class DownloadListener {
private final DoubleProperty percentage = new SimpleDoubleProperty(-1);
protected void progress(double percentage, int blocksLeft, Date date) {
UserThread.execute(() -> this.percentage.set(percentage / 100d));
}
protected void doneDownload() {
UserThread.execute(() -> this.percentage.set(1d));
}
public ReadOnlyDoubleProperty percentageProperty() {
return percentage;
}
}

View File

@ -151,7 +151,7 @@ public class WalletConfig extends AbstractIdleService {
protected volatile File vBtcWalletFile;
protected PeerAddress[] peerAddresses;
protected DownloadProgressTracker downloadListener;
protected DownloadListener downloadListener;
protected InputStream checkpoints;
protected String userAgent, version;
@Nullable
@ -234,7 +234,7 @@ public class WalletConfig extends AbstractIdleService {
* If you want to learn about the sync process, you can provide a listener here. For instance, a
* {@link DownloadProgressTracker} is a good choice.
*/
public WalletConfig setDownloadListener(DownloadProgressTracker listener) {
public WalletConfig setDownloadListener(DownloadListener listener) {
this.downloadListener = listener;
return this;
}
@ -388,7 +388,8 @@ public class WalletConfig extends AbstractIdleService {
System.out.println("Monero wallet uri: " + vXmrWallet.getRpcConnection().getUri());
// vXmrWallet.rescanSpent();
// vXmrWallet.rescanBlockchain();
vXmrWallet.sync();
vXmrWallet.sync(); // blocking
downloadListener.doneDownload();
vXmrWallet.save();
System.out.println("Loaded wallet balance: " + vXmrWallet.getBalance(0));
System.out.println("Loaded wallet unlocked balance: " + vXmrWallet.getUnlockedBalance(0));
@ -471,7 +472,7 @@ public class WalletConfig extends AbstractIdleService {
@Override
public void onSuccess(@Nullable Object result) {
//completeExtensionInitiations(vPeerGroup);
DownloadProgressTracker tracker = downloadListener == null ? new DownloadProgressTracker() : downloadListener;
DownloadProgressTracker tracker = new DownloadProgressTracker();
vPeerGroup.startBlockChainDownload(tracker);
}

View File

@ -45,11 +45,9 @@ import org.bitcoinj.core.Address;
import org.bitcoinj.core.BlockChain;
import org.bitcoinj.core.Context;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Peer;
import org.bitcoinj.core.PeerAddress;
import org.bitcoinj.core.PeerGroup;
import org.bitcoinj.core.RejectMessage;
import org.bitcoinj.core.listeners.DownloadProgressTracker;
import org.bitcoinj.utils.Threading;
import org.bitcoinj.wallet.DeterministicSeed;
import org.bitcoinj.wallet.Wallet;
@ -65,15 +63,15 @@ import com.google.common.util.concurrent.Service;
import org.apache.commons.lang3.StringUtils;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.LongProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleObjectProperty;
import java.net.InetAddress;
@ -85,7 +83,6 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -103,6 +100,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import monero.daemon.MoneroDaemon;
import monero.daemon.model.MoneroDaemonConnection;
import monero.wallet.MoneroWallet;
// Setup wallets and use WalletConfig for BitcoinJ wiring.
@ -112,6 +110,8 @@ import monero.wallet.MoneroWallet;
public class WalletsSetup {
public static final String PRE_SEGWIT_WALLET_BACKUP = "pre_segwit_haveno_BTC.wallet.backup";
private static final int MIN_BROADCAST_CONNECTIONS = 2;
private static final long DAEMON_POLL_INTERVAL_SECONDS = 20;
@Getter
public final BooleanProperty walletsSetupFailed = new SimpleBooleanProperty();
@ -135,9 +135,8 @@ public class WalletsSetup {
private final int walletRpcBindPort;
private final int socks5DiscoverMode;
private final IntegerProperty numPeers = new SimpleIntegerProperty(0);
private final IntegerProperty chainHeight = new SimpleIntegerProperty(0);
private final ObjectProperty<Peer> blocksDownloadedFromPeer = new SimpleObjectProperty<>();
private final ObjectProperty<List<Peer>> connectedPeers = new SimpleObjectProperty<>();
private final LongProperty chainHeight = new SimpleLongProperty(0);
private final ObjectProperty<List<MoneroDaemonConnection>> peerConnections = new SimpleObjectProperty<>();
private final DownloadListener downloadListener = new DownloadListener();
private final List<Runnable> setupCompletedHandlers = new ArrayList<>();
public final BooleanProperty shutDownComplete = new SimpleBooleanProperty();
@ -220,19 +219,11 @@ public class WalletsSetup {
if (preferences.getBitcoinNodes() != null && !preferences.getBitcoinNodes().isEmpty())
peerGroup.setAddPeersFromAddressMessage(false);
peerGroup.addConnectedEventListener((peer, peerCount) -> {
// We get called here on our user thread
numPeers.set(peerCount);
connectedPeers.set(peerGroup.getConnectedPeers());
});
peerGroup.addDisconnectedEventListener((peer, peerCount) -> {
// We get called here on our user thread
numPeers.set(peerCount);
connectedPeers.set(peerGroup.getConnectedPeers());
});
peerGroup.addBlocksDownloadedEventListener((peer, block, filteredBlock, blocksLeft) -> {
blocksDownloadedFromPeer.set(peer);
});
UserThread.runPeriodically(() -> {
peerConnections.set(getPeerConnections());
numPeers.set(peerConnections.get().size());
chainHeight.set(vXmrDaemon.getHeight());
}, DAEMON_POLL_INTERVAL_SECONDS);
// Need to be Threading.SAME_THREAD executor otherwise BitcoinJ will skip that listener
peerGroup.addPreMessageReceivedEventListener(Threading.SAME_THREAD, (peer, message) -> {
@ -247,16 +238,11 @@ public class WalletsSetup {
return message;
});
chain.addNewBestBlockListener(block -> {
UserThread.execute(() -> {
connectedPeers.set(peerGroup.getConnectedPeers());
chainHeight.set(block.getHeight());
});
});
// Map to user thread
UserThread.execute(() -> {
chainHeight.set(chain.getBestChainHeight());
peerConnections.set(getPeerConnections());
numPeers.set(peerConnections.get().size());
chainHeight.set(vXmrDaemon.getHeight());
addressEntryList.onWalletReady(walletConfig.btcWallet());
xmrAddressEntryList.onWalletReady(walletConfig.getXmrWallet());
timeoutTimer.stop();
@ -266,6 +252,12 @@ public class WalletsSetup {
// onSetupCompleted in walletAppKit is not the called on the last invocations, so we add a bit of delay
UserThread.runAfter(resultHandler::handleResult, 100, TimeUnit.MILLISECONDS);
}
private List<MoneroDaemonConnection> getPeerConnections() {
return vXmrDaemon.getConnections().stream()
.filter(peerConnection -> peerConnection.getPeer().isOnline())
.collect(Collectors.toList());
}
};
walletConfig.setSocks5Proxy(socks5Proxy);
walletConfig.setConfig(config);
@ -401,11 +393,10 @@ public class WalletsSetup {
}
private void configPeerNodes(@Nullable Socks5Proxy proxy) {
BtcNodesSetupPreferences btcNodesSetupPreferences = new BtcNodesSetupPreferences(preferences);
walletConfig.setMinBroadcastConnections(MIN_BROADCAST_CONNECTIONS);
BtcNodesSetupPreferences btcNodesSetupPreferences = new BtcNodesSetupPreferences(preferences);
List<BtcNode> nodes = btcNodesSetupPreferences.selectPreferredNodes(btcNodes);
int minBroadcastConnections = btcNodesSetupPreferences.calculateMinBroadcastConnections(nodes);
walletConfig.setMinBroadcastConnections(minBroadcastConnections);
BtcNodesRepository repository = new BtcNodesRepository(nodes);
boolean isUseClearNodesWithProxies = (useAllProvidedNodes || btcNodesSetupPreferences.isUseCustomNodes());
@ -515,18 +506,14 @@ public class WalletsSetup {
return numPeers;
}
public ReadOnlyObjectProperty<List<Peer>> connectedPeersProperty() {
return connectedPeers;
public ReadOnlyObjectProperty<List<MoneroDaemonConnection>> peerConnectionsProperty() {
return peerConnections;
}
public ReadOnlyIntegerProperty chainHeightProperty() {
public LongProperty chainHeightProperty() {
return chainHeight;
}
public ReadOnlyObjectProperty<Peer> blocksDownloadedFromPeerProperty() {
return blocksDownloadedFromPeer;
}
public ReadOnlyDoubleProperty downloadPercentageProperty() {
return downloadListener.percentageProperty();
}
@ -536,8 +523,9 @@ public class WalletsSetup {
}
public boolean isChainHeightSyncedWithinTolerance() {
int peersChainHeight = PeerGroup.getMostCommonChainHeight(connectedPeers.get());
int bestChainHeight = walletConfig.chain().getBestChainHeight();
Long peersChainHeight = walletConfig.vXmrDaemon.getSyncInfo().getTargetHeight();
if (peersChainHeight == 0) return true; // monero-daemon-rpc sync_info's target_height returns 0 when node is fully synced
long bestChainHeight = chainHeight.get();
if (Math.abs(peersChainHeight - bestChainHeight) <= 3) {
return true;
}
@ -566,28 +554,4 @@ public class WalletsSetup {
return walletConfig.getMinBroadcastConnections();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Inner classes
///////////////////////////////////////////////////////////////////////////////////////////
private static class DownloadListener extends DownloadProgressTracker {
private final DoubleProperty percentage = new SimpleDoubleProperty(-1);
@Override
protected void progress(double percentage, int blocksLeft, Date date) {
super.progress(percentage, blocksLeft, date);
UserThread.execute(() -> this.percentage.set(percentage / 100d));
}
@Override
protected void doneDownload() {
super.doneDownload();
UserThread.execute(() -> this.percentage.set(1d));
}
public ReadOnlyDoubleProperty percentageProperty() {
return percentage;
}
}
}

View File

@ -81,7 +81,7 @@ public class XmrTxProofService implements AssetTxProofService {
private final Map<String, XmrTxProofRequestsPerTrade> servicesByTradeId = new HashMap<>();
private AutoConfirmSettings autoConfirmSettings;
private final Map<String, ChangeListener<Trade.State>> tradeStateListenerMap = new HashMap<>();
private ChangeListener<Number> btcPeersListener, btcBlockListener;
private ChangeListener<Number> xmrPeersListener, xmrBlockListener;
private BootstrapListener bootstrapListener;
private MonadicBinding<Boolean> p2pNetworkAndWalletReady;
private ChangeListener<Boolean> p2pNetworkAndWalletReadyListener;
@ -126,12 +126,12 @@ public class XmrTxProofService implements AssetTxProofService {
// onAllServicesInitialized is called once we have received the initial data but we want to have our
// hidden service published and upDatedDataResponse received before we start.
BooleanProperty isP2pBootstrapped = isP2pBootstrapped();
BooleanProperty hasSufficientBtcPeers = hasSufficientBtcPeers();
BooleanProperty isBtcBlockDownloadComplete = isBtcBlockDownloadComplete();
if (isP2pBootstrapped.get() && hasSufficientBtcPeers.get() && isBtcBlockDownloadComplete.get()) {
BooleanProperty hasSufficientXmrPeers = hasSufficientXmrPeers();
BooleanProperty isXmrBlockDownloadComplete = isXmrBlockDownloadComplete();
if (isP2pBootstrapped.get() && hasSufficientXmrPeers.get() && isXmrBlockDownloadComplete.get()) {
onP2pNetworkAndWalletReady();
} else {
p2pNetworkAndWalletReady = EasyBind.combine(isP2pBootstrapped, hasSufficientBtcPeers, isBtcBlockDownloadComplete,
p2pNetworkAndWalletReady = EasyBind.combine(isP2pBootstrapped, hasSufficientXmrPeers, isXmrBlockDownloadComplete,
(bootstrapped, sufficientPeers, downloadComplete) ->
bootstrapped && sufficientPeers && downloadComplete);
@ -287,34 +287,34 @@ public class XmrTxProofService implements AssetTxProofService {
// Startup checks
///////////////////////////////////////////////////////////////////////////////////////////
private BooleanProperty isBtcBlockDownloadComplete() {
private BooleanProperty isXmrBlockDownloadComplete() {
BooleanProperty result = new SimpleBooleanProperty();
if (walletsSetup.isDownloadComplete()) {
result.set(true);
} else {
btcBlockListener = (observable, oldValue, newValue) -> {
xmrBlockListener = (observable, oldValue, newValue) -> {
if (walletsSetup.isDownloadComplete()) {
walletsSetup.downloadPercentageProperty().removeListener(btcBlockListener);
walletsSetup.downloadPercentageProperty().removeListener(xmrBlockListener);
result.set(true);
}
};
walletsSetup.downloadPercentageProperty().addListener(btcBlockListener);
walletsSetup.downloadPercentageProperty().addListener(xmrBlockListener);
}
return result;
}
private BooleanProperty hasSufficientBtcPeers() {
private BooleanProperty hasSufficientXmrPeers() {
BooleanProperty result = new SimpleBooleanProperty();
if (walletsSetup.hasSufficientPeersForBroadcast()) {
result.set(true);
} else {
btcPeersListener = (observable, oldValue, newValue) -> {
xmrPeersListener = (observable, oldValue, newValue) -> {
if (walletsSetup.hasSufficientPeersForBroadcast()) {
walletsSetup.numPeersProperty().removeListener(btcPeersListener);
walletsSetup.numPeersProperty().removeListener(xmrPeersListener);
result.set(true);
}
};
walletsSetup.numPeersProperty().addListener(btcPeersListener);
walletsSetup.numPeersProperty().addListener(xmrPeersListener);
}
return result;
}

View File

@ -17,28 +17,28 @@
package bisq.desktop.main.settings.network;
import org.bitcoinj.core.Peer;
import monero.daemon.model.MoneroDaemonConnection;
public class BitcoinNetworkListItem {
private final Peer peer;
public class MoneroNetworkListItem {
private final MoneroDaemonConnection peerConnection;
public BitcoinNetworkListItem(Peer peer) {
this.peer = peer;
public MoneroNetworkListItem(MoneroDaemonConnection peerConnection) {
this.peerConnection = peerConnection;
}
public String getOnionAddress() {
return peer.getAddress().toString();
return peerConnection.getPeer().getHost() + ":" + peerConnection.getPeer().getPort();
}
public String getVersion() {
return String.valueOf(peer.getPeerVersionMessage().clientVersion);
return "";
}
public String getSubVersion() {
return peer.getPeerVersionMessage().subVer;
return "";
}
public String getHeight() {
return String.valueOf(peer.getBestHeight());
return String.valueOf(peerConnection.getHeight());
}
}

View File

@ -46,24 +46,24 @@
<TitledGroupBg fx:id="btcHeader" GridPane.rowSpan="5"/>
<VBox GridPane.rowIndex="0" GridPane.hgrow="ALWAYS" GridPane.vgrow="SOMETIMES">
<AutoTooltipLabel fx:id="bitcoinPeersLabel" styleClass="small-text"/>
<TableView fx:id="bitcoinPeersTableView">
<TableView fx:id="moneroPeersTableView">
<columns>
<TableColumn fx:id="bitcoinPeerAddressColumn" minWidth="220">
<TableColumn fx:id="moneroPeerAddressColumn" minWidth="220">
<cellValueFactory>
<PropertyValueFactory property="onionAddress"/>
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="bitcoinPeerVersionColumn" minWidth="80" maxWidth="90">
<TableColumn fx:id="moneroPeerVersionColumn" minWidth="80" maxWidth="90">
<cellValueFactory>
<PropertyValueFactory property="version"/>
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="bitcoinPeerSubVersionColumn" minWidth="180" maxWidth="180">
<TableColumn fx:id="moneroPeerSubVersionColumn" minWidth="180" maxWidth="180">
<cellValueFactory>
<PropertyValueFactory property="subVersion"/>
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="bitcoinPeerHeightColumn" minWidth="80" maxWidth="80">
<TableColumn fx:id="moneroPeerHeightColumn" minWidth="80" maxWidth="80">
<cellValueFactory>
<PropertyValueFactory property="height"/>
</cellValueFactory>

View File

@ -45,8 +45,6 @@ import bisq.network.p2p.network.Statistic;
import bisq.common.ClockWatcher;
import bisq.common.UserThread;
import org.bitcoinj.core.PeerGroup;
import javax.inject.Inject;
import javafx.fxml.FXML;
@ -73,11 +71,14 @@ import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.SortedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static javafx.beans.binding.Bindings.createStringBinding;
import monero.daemon.model.MoneroDaemonConnection;
@FxmlView
public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
@ -98,13 +99,13 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
@FXML
TableView<P2pNetworkListItem> p2pPeersTableView;
@FXML
TableView<BitcoinNetworkListItem> bitcoinPeersTableView;
TableView<MoneroNetworkListItem> moneroPeersTableView;
@FXML
TableColumn<P2pNetworkListItem, String> onionAddressColumn, connectionTypeColumn, creationDateColumn,
roundTripTimeColumn, sentBytesColumn, receivedBytesColumn, peerTypeColumn;
@FXML
TableColumn<BitcoinNetworkListItem, String> bitcoinPeerAddressColumn, bitcoinPeerVersionColumn,
bitcoinPeerSubVersionColumn, bitcoinPeerHeightColumn;
TableColumn<MoneroNetworkListItem, String> moneroPeerAddressColumn, moneroPeerVersionColumn,
moneroPeerSubVersionColumn, moneroPeerHeightColumn;
@FXML
Label reSyncSPVChainLabel;
@FXML
@ -122,13 +123,12 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
private final ObservableList<P2pNetworkListItem> p2pNetworkListItems = FXCollections.observableArrayList();
private final SortedList<P2pNetworkListItem> p2pSortedList = new SortedList<>(p2pNetworkListItems);
private final ObservableList<BitcoinNetworkListItem> bitcoinNetworkListItems = FXCollections.observableArrayList();
private final SortedList<BitcoinNetworkListItem> bitcoinSortedList = new SortedList<>(bitcoinNetworkListItems);
private final ObservableList<MoneroNetworkListItem> moneroNetworkListItems = FXCollections.observableArrayList();
private final SortedList<MoneroNetworkListItem> moneroSortedList = new SortedList<>(moneroNetworkListItems);
private Subscription numP2PPeersSubscription;
private Subscription bitcoinPeersSubscription;
private Subscription bitcoinBlockHeightSubscription;
private Subscription bitcoinBlocksDownloadedSubscription;
private Subscription moneroPeersSubscription;
private Subscription moneroBlockHeightSubscription;
private Subscription nodeAddressSubscription;
private ChangeListener<Boolean> btcNodesInputTextFieldFocusListener;
private ToggleGroup bitcoinPeersToggleGroup;
@ -156,6 +156,7 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
this.clockWatcher = clockWatcher;
}
@Override
public void initialize() {
btcHeader.setText(Res.get("settings.net.btcHeader"));
p2pHeader.setText(Res.get("settings.net.p2pHeader"));
@ -164,11 +165,11 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
bitcoinPeersLabel.setText(Res.get("settings.net.bitcoinPeersLabel"));
useTorForBtcJCheckBox.setText(Res.get("settings.net.useTorForBtcJLabel"));
bitcoinNodesLabel.setText(Res.get("settings.net.bitcoinNodesLabel"));
bitcoinPeerAddressColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.onionAddressColumn")));
bitcoinPeerAddressColumn.getStyleClass().add("first-column");
bitcoinPeerVersionColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.versionColumn")));
bitcoinPeerSubVersionColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.subVersionColumn")));
bitcoinPeerHeightColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.heightColumn")));
moneroPeerAddressColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.onionAddressColumn")));
moneroPeerAddressColumn.getStyleClass().add("first-column");
moneroPeerVersionColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.versionColumn")));
moneroPeerSubVersionColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.subVersionColumn")));
moneroPeerHeightColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.heightColumn")));
localhostBtcNodeInfoLabel.setText(Res.get("settings.net.localhostBtcNodeInfo"));
useProvidedNodesRadio.setText(Res.get("settings.net.useProvidedNodesRadio"));
useCustomNodesRadio.setText(Res.get("settings.net.useCustomNodesRadio"));
@ -196,12 +197,12 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
GridPane.setMargin(p2PPeersLabel, new Insets(4, 0, 0, 0));
GridPane.setValignment(p2PPeersLabel, VPos.TOP);
bitcoinPeersTableView.setMinHeight(180);
bitcoinPeersTableView.setPrefHeight(180);
bitcoinPeersTableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
bitcoinPeersTableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noData")));
bitcoinPeersTableView.getSortOrder().add(bitcoinPeerAddressColumn);
bitcoinPeerAddressColumn.setSortType(TableColumn.SortType.ASCENDING);
moneroPeersTableView.setMinHeight(180);
moneroPeersTableView.setPrefHeight(180);
moneroPeersTableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
moneroPeersTableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noData")));
moneroPeersTableView.getSortOrder().add(moneroPeerAddressColumn);
moneroPeerAddressColumn.setSortType(TableColumn.SortType.ASCENDING);
p2pPeersTableView.setMinHeight(180);
@ -290,14 +291,11 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
reSyncSPVChainButton.setOnAction(event -> GUIUtil.reSyncSPVChain(preferences));
bitcoinPeersSubscription = EasyBind.subscribe(walletsSetup.connectedPeersProperty(),
connectedPeers -> updateBitcoinPeersTable());
moneroPeersSubscription = EasyBind.subscribe(walletsSetup.peerConnectionsProperty(),
this::updateMoneroPeersTable);
bitcoinBlocksDownloadedSubscription = EasyBind.subscribe(walletsSetup.blocksDownloadedFromPeerProperty(),
peer -> updateBitcoinPeersTable());
bitcoinBlockHeightSubscription = EasyBind.subscribe(walletsSetup.chainHeightProperty(),
chainHeight -> updateBitcoinPeersTable());
moneroBlockHeightSubscription = EasyBind.subscribe(walletsSetup.chainHeightProperty(),
this::updateChainHeightTextField);
nodeAddressSubscription = EasyBind.subscribe(p2PService.getNetworkNode().nodeAddressProperty(),
nodeAddress -> onionAddress.setText(nodeAddress == null ?
@ -317,8 +315,8 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
Statistic.numTotalReceivedMessagesPerSecProperty().get()),
Statistic.numTotalReceivedMessagesPerSecProperty()));
bitcoinSortedList.comparatorProperty().bind(bitcoinPeersTableView.comparatorProperty());
bitcoinPeersTableView.setItems(bitcoinSortedList);
moneroSortedList.comparatorProperty().bind(moneroPeersTableView.comparatorProperty());
moneroPeersTableView.setItems(moneroSortedList);
p2pSortedList.comparatorProperty().bind(p2pPeersTableView.comparatorProperty());
p2pPeersTableView.setItems(p2pSortedList);
@ -340,14 +338,11 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
if (nodeAddressSubscription != null)
nodeAddressSubscription.unsubscribe();
if (bitcoinPeersSubscription != null)
bitcoinPeersSubscription.unsubscribe();
if (moneroPeersSubscription != null)
moneroPeersSubscription.unsubscribe();
if (bitcoinBlockHeightSubscription != null)
bitcoinBlockHeightSubscription.unsubscribe();
if (bitcoinBlocksDownloadedSubscription != null)
bitcoinBlocksDownloadedSubscription.unsubscribe();
if (moneroBlockHeightSubscription != null)
moneroBlockHeightSubscription.unsubscribe();
if (numP2PPeersSubscription != null)
numP2PPeersSubscription.unsubscribe();
@ -355,7 +350,7 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
sentDataTextField.textProperty().unbind();
receivedDataTextField.textProperty().unbind();
bitcoinSortedList.comparatorProperty().unbind();
moneroSortedList.comparatorProperty().unbind();
p2pSortedList.comparatorProperty().unbind();
p2pPeersTableView.getItems().forEach(P2pNetworkListItem::cleanup);
btcNodesInputTextField.focusedProperty().removeListener(btcNodesInputTextFieldFocusListener);
@ -485,14 +480,17 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
.collect(Collectors.toList()));
}
private void updateBitcoinPeersTable() {
bitcoinNetworkListItems.clear();
bitcoinNetworkListItems.setAll(walletsSetup.getPeerGroup().getConnectedPeers().stream()
.map(BitcoinNetworkListItem::new)
private void updateMoneroPeersTable(List<MoneroDaemonConnection> peerConnections) {
moneroNetworkListItems.clear();
moneroNetworkListItems.setAll(peerConnections.stream()
.map(MoneroNetworkListItem::new)
.collect(Collectors.toList()));
}
private void updateChainHeightTextField(Number chainHeight) {
chainHeightTextField.textProperty().setValue(Res.get("settings.net.chainHeight",
walletsSetup.chainHeightProperty().get(),
PeerGroup.getMostCommonChainHeight(walletsSetup.connectedPeersProperty().get())));
null,
chainHeight));
}
}

View File

@ -785,7 +785,7 @@ public class GUIUtil {
}
public static boolean canCreateOrTakeOfferOrShowPopup(User user, Navigation navigation) {
// TODO (woodser): use refund agents to dispute arbitration?
if (!user.hasAcceptedRefundAgents()) {
log.warn("There are no refund agents available"); // TODO (woodser): refund agents changing from [4444] to [] causing this error

View File

@ -11,22 +11,15 @@ On Ubuntu: `sudo apt install make wget git git-lfs openjdk-11-jdk`. The Bitcoin
1. Download this repository: `git clone https://github.com/haveno-dex/haveno.git`
2. Navigate to the root of the repository (`cd haveno`) and build the repository: run `make` in the terminal and wait until the process is completed (this will also download and verify the Monero and Bitcoin binaries).
## 3. Run Bitcoin
## 3. Connect to Monero stagenet
Run each of these commands in their own terminal window:
The quickest way to get a Monero stagenet running is by connecting to our own shared instance (3a) so you won't have to do anything except mine coins for testing (step 5). If you prefer to have total control over the testing instance, you might prefer running your own private Monero stagenet (3b).
1. Run Bitcoin: `make bitcoind`
2. Create bitcoin blocks: `make btc-blocks` (after running the command, this terminal window can be closed)
## 4. Connect to Monero stagenet
The quickest way to get a Monero stagenet running is by connecting to our own shared instance (4a) so you won't have to do anything except mine coins for testing (step 6). If you prefer to have total control over the testing instance, you might prefer running your own private Monero stagenet (4b).
### 4a. Join our shared stagenet
### 3a. Join our shared stagenet
Run `make monero-shared`
### 4b. Run your own private stagenet
### 3b. Run your own private stagenet
1. In a new terminal window run `make monero-private1`;
1. In a new terminal window run `make monero-private2`;
@ -34,7 +27,7 @@ Run `make monero-shared`
`start_mining 56k9Yra1pxwcTYzqKcnLip8mymSQdEfA6V7476W9XhSiHPp1hAboo1F6na7kxTxwvXU6JjDQtu8VJdGj9FEcjkxGJfsyyah 1`
## 5. Deploy
## 4. Deploy
If you are a *screen* user, simply run `make deploy`. This command will open all needed Haveno instances (seednode, Alice, Bob, arbitrator) using *screen*. If this is the first time launching the arbitrator desktop application, register the arbitrator and mediator as explained in steps `5.3.1` and `5.3.2`.
@ -48,14 +41,14 @@ If you don't use *screen*, open 4 terminal windows and run in each one of them:
4. `make alice-desktop` or if you want to run Alice as a daemon: `make alice-daemon`
5. `make bob-desktop` or if you want to run Bob as a daemon: `make bob-daemon`
## 6. Fund your wallets
## 5. Fund your wallets
When running Alice and Bob, you'll see a Monero address prompted in the terminal. Send stagenet XMR to the addresses of both Alice and Bob to be able to initiate a trade.
You can fund the two wallets by mining some stagenet XMR coins to those addresses. To do so, open a terminal where you ran monerod and run: `start_mining ADDRESS 1`.
monerod will start mining stagenet coins on your device using one thread. Replace `ADDRESS` with the address of Alice first, and then Bob's.
monerod will start mining stagenet coins on your device using one thread. Replace `ADDRESS` with the address of Alice first, and then Bob's. Run `stop_mining` to stop mining.
## 7. Start testing
## 6. Start testing
You are all set. Now that everything is running and your wallets are funded, you can create test trades between Alice and Bob. Remember to mine a few blocks after opening and accepting the test trade so the transaction will be confirmed.

View File

@ -97,8 +97,8 @@ while true; do
cd .localnet
if ! is_linux && ! is_mac; then
bins_deps=("bitcoind" "bitcoin-cli" "monerod" "monero-wallet-rpc")
bins_deps=("monerod" "monero-wallet-rpc") # "bitcoind" "bitcoin-cli"
for i in ${bins_deps[@]}; do
[ -f "$i" ] || { echo "${i} not found."; echo "Dependencies are installed automatically only on Linux and Mac. Please manually install bitcoind, bitcoin-cli, monerod, and monero-wallet-rpc executables into haveno/.localnet/ before running make."; exit 1; }
done
@ -106,6 +106,6 @@ while true; do
fi
dw_monero
dw_bitcoin
# dw_bitcoin
exit 0
done