Skip to content

Commit

Permalink
Merge pull request #4764 from jmacxx/fix_issue_4727
Browse files Browse the repository at this point in the history
Don't allow trade start if BitcoinJ is not fully synced
  • Loading branch information
ripcurlx authored Nov 11, 2020
2 parents f6a2f3d + 0ddd333 commit 0c47cf0
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 14 deletions.
11 changes: 11 additions & 0 deletions core/src/main/java/bisq/core/btc/setup/WalletsSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ protected void onSetupCompleted() {
return message;
});

chainHeight.set(chain.getBestChainHeight());
chain.addNewBestBlockListener(block -> {
connectedPeers.set(peerGroup.getConnectedPeers());
chainHeight.set(block.getHeight());
Expand Down Expand Up @@ -522,6 +523,16 @@ public boolean isDownloadComplete() {
return downloadPercentageProperty().get() == 1d;
}

public boolean isChainHeightSyncedWithinTolerance() {
int peersChainHeight = PeerGroup.getMostCommonChainHeight(connectedPeers.get());
int bestChainHeight = walletConfig.chain().getBestChainHeight();
if (peersChainHeight - bestChainHeight <= 3) {
return true;
}
log.warn("Our chain height: {} is out of sync with peer nodes chain height: {}", chainHeight.get(), peersChainHeight);
return false;
}

public Set<Address> getAddressesByContext(@SuppressWarnings("SameParameterValue") AddressEntry.Context context) {
return addressEntryList.getAddressEntriesAsListImmutable().stream()
.filter(addressEntry -> addressEntry.getContext() == context)
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/bisq/core/btc/wallet/WalletService.java
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,10 @@ public int getBestChainHeight() {
return isWalletReady() && chain != null ? chain.getBestChainHeight() : 0;
}

public boolean isChainHeightSyncedWithinTolerance() {
return walletsSetup.isChainHeightSyncedWithinTolerance();
}

public Transaction getClonedTransaction(Transaction tx) {
return new Transaction(params, tx.bitcoinSerialize());
}
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/java/bisq/core/offer/OpenOfferManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,14 @@ private void handleOfferAvailabilityRequest(OfferAvailabilityRequest request, No
return;
}

// Don't allow trade start if BitcoinJ is not fully synced (bisq issue #4764)
if (!btcWalletService.isChainHeightSyncedWithinTolerance()) {
errorMessage = "We got a handleOfferAvailabilityRequest but our chain is not synced.";
log.info(errorMessage);
sendAckMessage(request, peer, false, errorMessage);
return;
}

if (stopped) {
errorMessage = "We have stopped already. We ignore that handleOfferAvailabilityRequest call.";
log.debug(errorMessage);
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,7 @@ settings.net.creationDateColumn=Established
settings.net.connectionTypeColumn=In/Out
settings.net.sentDataLabel=Sent data statistics
settings.net.receivedDataLabel=Received data statistics
settings.net.chainHeightLabel=Latest BTC block height
settings.net.roundTripTimeColumn=Roundtrip
settings.net.sentBytesColumn=Sent
settings.net.receivedBytesColumn=Received
Expand All @@ -1289,6 +1290,7 @@ settings.net.needRestart=You need to restart the application to apply that chang
settings.net.notKnownYet=Not known yet...
settings.net.sentData=Sent data: {0}, {1} messages, {2} messages/sec
settings.net.receivedData=Received data: {0}, {1} messages, {2} messages/sec
settings.net.chainHeight=Bisq: {0} | Peers: {1}
settings.net.ips=[IP address:port | host name:port | onion address:port] (comma separated). Port can be omitted if default is used (8333).
settings.net.seedNode=Seed node
settings.net.directPeer=Peer (direct)
Expand Down Expand Up @@ -2781,6 +2783,8 @@ popup.warning.noMediatorsAvailable=There are no mediators available.
popup.warning.notFullyConnected=You need to wait until you are fully connected to the network.\nThat might take up to about 2 minutes at startup.
popup.warning.notSufficientConnectionsToBtcNetwork=You need to wait until you have at least {0} connections to the Bitcoin network.
popup.warning.downloadNotComplete=You need to wait until the download of missing Bitcoin blocks is complete.
popup.warning.chainNotSynced=The Bisq wallet blockchain height is not synced correctly. If you recently started the application, please wait until one Bitcoin block has been published.\n\n\
You can check the blockchain height in Settings/Network Info. If more than one block passes and this problem persists it may be stalled, in which case you should do an SPV resync. [HYPERLINK:https://bisq.wiki/Resyncing_SPV_file]
popup.warning.removeOffer=Are you sure you want to remove that offer?\nThe maker fee of {0} will be lost if you remove that offer.
popup.warning.tooLargePercentageValue=You cannot set a percentage of 100% or larger.
popup.warning.examplePercentageValue=Please enter a percentage number like \"5.4\" for 5.4%
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import bisq.desktop.util.GUIUtil;

import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.btc.setup.WalletsSetup;
import bisq.core.filter.FilterManager;
import bisq.core.locale.BankUtil;
import bisq.core.locale.CountryUtil;
Expand Down Expand Up @@ -99,6 +100,7 @@ class OfferBookViewModel extends ActivatableViewModel {
private final User user;
private final OfferBook offerBook;
final Preferences preferences;
private final WalletsSetup walletsSetup;
private final P2PService p2PService;
final PriceFeedService priceFeedService;
private final ClosedTradableManager closedTradableManager;
Expand Down Expand Up @@ -142,6 +144,7 @@ public OfferBookViewModel(User user,
OpenOfferManager openOfferManager,
OfferBook offerBook,
Preferences preferences,
WalletsSetup walletsSetup,
P2PService p2PService,
PriceFeedService priceFeedService,
ClosedTradableManager closedTradableManager,
Expand All @@ -156,6 +159,7 @@ public OfferBookViewModel(User user,
this.user = user;
this.offerBook = offerBook;
this.preferences = preferences;
this.walletsSetup = walletsSetup;
this.p2PService = p2PService;
this.priceFeedService = priceFeedService;
this.closedTradableManager = closedTradableManager;
Expand Down Expand Up @@ -532,6 +536,7 @@ boolean hasPaymentAccountForCurrency() {

boolean canCreateOrTakeOffer() {
return GUIUtil.canCreateOrTakeOfferOrShowPopup(user, navigation) &&
GUIUtil.isChainHeightSyncedWithinToleranceOrShowPopup(walletsSetup) &&
GUIUtil.isBootstrappedOrShowPopup(p2PService);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
<AutoTooltipButton fx:id="reSyncSPVChainButton"/>
</VBox>

<TitledGroupBg fx:id="p2pHeader" GridPane.rowIndex="5" GridPane.rowSpan="4">
<TitledGroupBg fx:id="p2pHeader" GridPane.rowIndex="5" GridPane.rowSpan="5">
<padding>
<Insets top="50.0"/>
</padding>
Expand Down Expand Up @@ -159,7 +159,10 @@
<BisqTextField fx:id="receivedDataTextField" GridPane.rowIndex="8" editable="false"
focusTraversable="false" labelFloat="true"/>

<AutoTooltipButton fx:id="openTorSettingsButton" GridPane.rowIndex="9" GridPane.columnIndex="0"/>
<BisqTextField fx:id="chainHeightTextField" GridPane.rowIndex="9" editable="false"
focusTraversable="false" labelFloat="true"/>

<AutoTooltipButton fx:id="openTorSettingsButton" GridPane.rowIndex="10" GridPane.columnIndex="0"/>

<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" minWidth="500"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
import bisq.common.ClockWatcher;
import bisq.common.UserThread;

import org.bitcoinj.core.PeerGroup;

import javax.inject.Inject;

import javafx.fxml.FXML;
Expand Down Expand Up @@ -86,7 +88,7 @@ public class NetworkSettingsView extends ActivatableView<GridPane, Void> {
@FXML
InputTextField btcNodesInputTextField;
@FXML
TextField onionAddress, sentDataTextField, receivedDataTextField;
TextField onionAddress, sentDataTextField, receivedDataTextField, chainHeightTextField;
@FXML
Label p2PPeersLabel, bitcoinPeersLabel;
@FXML
Expand Down Expand Up @@ -180,6 +182,7 @@ public void initialize() {
connectionTypeColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.connectionTypeColumn")));
sentDataTextField.setPromptText(Res.get("settings.net.sentDataLabel"));
receivedDataTextField.setPromptText(Res.get("settings.net.receivedDataLabel"));
chainHeightTextField.setPromptText(Res.get("settings.net.chainHeightLabel"));
roundTripTimeColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.roundTripTimeColumn")));
sentBytesColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.sentBytesColumn")));
receivedBytesColumn.setGraphic(new AutoTooltipLabel(Res.get("settings.net.receivedBytesColumn")));
Expand Down Expand Up @@ -487,6 +490,9 @@ private void updateBitcoinPeersTable() {
bitcoinNetworkListItems.setAll(walletsSetup.getPeerGroup().getConnectedPeers().stream()
.map(BitcoinNetworkListItem::new)
.collect(Collectors.toList()));
chainHeightTextField.textProperty().setValue(Res.get("settings.net.chainHeight",
walletsSetup.chainHeightProperty().get(),
PeerGroup.getMostCommonChainHeight(walletsSetup.connectedPeersProperty().get())));
}
}

9 changes: 9 additions & 0 deletions desktop/src/main/java/bisq/desktop/util/GUIUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,15 @@ public static boolean isReadyForTxBroadcastOrShowPopup(P2PService p2PService, Wa
return true;
}

public static boolean isChainHeightSyncedWithinToleranceOrShowPopup(WalletsSetup walletsSetup) {
if (!walletsSetup.isChainHeightSyncedWithinTolerance()) {
new Popup().information(Res.get("popup.warning.chainNotSynced")).show();
return false;
}

return true;
}

public static boolean canCreateOrTakeOfferOrShowPopup(User user, Navigation navigation) {
if (!user.hasAcceptedRefundAgents()) {
new Popup().warning(Res.get("popup.warning.noArbitratorsAvailable")).show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public void testMaxCharactersForAmountWithNoOffes() {

when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);

final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());
assertEquals(0, model.maxPlacesForAmount.intValue());
}
Expand All @@ -243,7 +243,7 @@ public void testMaxCharactersForAmount() {

when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);

final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());
model.activate();

Expand All @@ -261,7 +261,7 @@ public void testMaxCharactersForAmountRange() {

when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);

final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());
model.activate();

Expand All @@ -280,7 +280,7 @@ public void testMaxCharactersForVolumeWithNoOffes() {

when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);

final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());
assertEquals(0, model.maxPlacesForVolume.intValue());
}
Expand All @@ -294,7 +294,7 @@ public void testMaxCharactersForVolume() {

when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);

final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());
model.activate();

Expand All @@ -312,7 +312,7 @@ public void testMaxCharactersForVolumeRange() {

when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);

final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());
model.activate();

Expand All @@ -331,7 +331,7 @@ public void testMaxCharactersForPriceWithNoOffers() {

when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);

final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());
assertEquals(0, model.maxPlacesForPrice.intValue());
}
Expand All @@ -345,7 +345,7 @@ public void testMaxCharactersForPrice() {

when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);

final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());
model.activate();

Expand All @@ -363,7 +363,7 @@ public void testMaxCharactersForPriceDistanceWithNoOffers() {

when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);

final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());
assertEquals(0, model.maxPlacesForMarketPriceMargin.intValue());
}
Expand Down Expand Up @@ -391,7 +391,7 @@ public void testMaxCharactersForPriceDistance() {
item4.getOffer().setPriceFeedService(priceFeedService);
offerBookListItems.addAll(item1, item2);

final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, priceFeedService,
final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, priceFeedService,
null, null, null, null, coinFormatter, new BsqFormatter());
model.activate();

Expand All @@ -412,7 +412,7 @@ public void testGetPrice() {
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
when(priceFeedService.getMarketPrice(anyString())).thenReturn(new MarketPrice("USD", 12684.0450, Instant.now().getEpochSecond(), true));

final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null,
final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null,
null, null, null, null, coinFormatter, new BsqFormatter());

final OfferBookListItem item = make(btcBuyItem.but(
Expand Down

0 comments on commit 0c47cf0

Please sign in to comment.