diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/network/RepublishGovernanceDataHandler.java b/core/src/main/java/bisq/core/dao/governance/blindvote/network/RepublishGovernanceDataHandler.java index ea73a102c26..9701159f721 100644 --- a/core/src/main/java/bisq/core/dao/governance/blindvote/network/RepublishGovernanceDataHandler.java +++ b/core/src/main/java/bisq/core/dao/governance/blindvote/network/RepublishGovernanceDataHandler.java @@ -102,7 +102,7 @@ private void sendRepublishRequest(NodeAddress nodeAddress) { connectToNextNode(); } else { log.warn("We have stopped already. We ignore that timeoutTimer.run call. " + - "Might be caused by an previous networkNode.sendMessage.onFailure."); + "Might be caused by a previous networkNode.sendMessage.onFailure."); } }, TIMEOUT); @@ -118,7 +118,7 @@ public void onSuccess(Connection connection) { stop(); } else { log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call." + - "Might be caused by an previous timeout."); + "Might be caused by a previous timeout."); } } @@ -133,7 +133,7 @@ public void onFailure(@NotNull Throwable throwable) { connectToNextNode(); } else { log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call. " + - "Might be caused by an previous timeout."); + "Might be caused by a previous timeout."); } } }, MoreExecutors.directExecutor()); diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/RequestStateHashesHandler.java b/core/src/main/java/bisq/core/dao/monitoring/network/RequestStateHashesHandler.java index cc41c56ef62..602677121b2 100644 --- a/core/src/main/java/bisq/core/dao/monitoring/network/RequestStateHashesHandler.java +++ b/core/src/main/java/bisq/core/dao/monitoring/network/RequestStateHashesHandler.java @@ -116,7 +116,7 @@ public void requestStateHashes(int fromHeight) { handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_TIMEOUT); } else { log.trace("We have stopped already. We ignore that timeoutTimer.run call. " + - "Might be caused by an previous networkNode.sendMessage.onFailure."); + "Might be caused by a previous networkNode.sendMessage.onFailure."); } }, TIMEOUT); @@ -134,7 +134,7 @@ public void onSuccess(Connection connection) { nodeAddress.getFullAddress()); } else { log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call." + - "Might be caused by an previous timeout."); + "Might be caused by a previous timeout."); } } @@ -149,7 +149,7 @@ public void onFailure(@NotNull Throwable throwable) { handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_FAILURE); } else { log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call. " + - "Might be caused by an previous timeout."); + "Might be caused by a previous timeout."); } } }, MoreExecutors.directExecutor()); diff --git a/core/src/main/java/bisq/core/dao/node/BsqNode.java b/core/src/main/java/bisq/core/dao/node/BsqNode.java index e06be387575..2e0bdfef4d4 100644 --- a/core/src/main/java/bisq/core/dao/node/BsqNode.java +++ b/core/src/main/java/bisq/core/dao/node/BsqNode.java @@ -189,7 +189,7 @@ protected int getStartBlockHeight() { if (chainHeight > genesisBlockHeight) startBlockHeight = chainHeight + 1; - log.info("Start parse blocks:\n" + + log.info("getStartBlockHeight:\n" + " Start block height={}\n" + " Genesis txId={}\n" + " Genesis block height={}\n" + @@ -223,15 +223,14 @@ protected Optional doParseBlock(RawBlock rawBlock) throws RequiredReorgFr // height we have no block but chainHeight is initially set to genesis height (bad design ;-( but a bit tricky // to change now as it used in many areas.) if (daoStateService.getBlockAtHeight(rawBlock.getHeight()).isPresent()) { - log.debug("We have already a block with the height of the new block. Height of new block={}", rawBlock.getHeight()); + log.info("We have already a block with the height of the new block. Height of new block={}", rawBlock.getHeight()); return Optional.empty(); } try { Block block = blockParser.parseBlock(rawBlock); - if (pendingBlocks.contains(rawBlock)) - pendingBlocks.remove(rawBlock); + pendingBlocks.remove(rawBlock); // After parsing we check if we have pending blocks we might have received earlier but which have been // not connecting from the latest height we had. The list is sorted by height diff --git a/core/src/main/java/bisq/core/dao/node/explorer/JsonTxOutputType.java b/core/src/main/java/bisq/core/dao/node/explorer/JsonTxOutputType.java index 0018f273d50..a5657bfaf86 100644 --- a/core/src/main/java/bisq/core/dao/node/explorer/JsonTxOutputType.java +++ b/core/src/main/java/bisq/core/dao/node/explorer/JsonTxOutputType.java @@ -43,7 +43,7 @@ enum JsonTxOutputType { INVALID_OUTPUT("Invalid"); @Getter - private String displayString; + private final String displayString; JsonTxOutputType(String displayString) { this.displayString = displayString; diff --git a/core/src/main/java/bisq/core/dao/node/explorer/JsonTxType.java b/core/src/main/java/bisq/core/dao/node/explorer/JsonTxType.java index d14e17f8a56..ee8ffd25279 100644 --- a/core/src/main/java/bisq/core/dao/node/explorer/JsonTxType.java +++ b/core/src/main/java/bisq/core/dao/node/explorer/JsonTxType.java @@ -40,7 +40,7 @@ enum JsonTxType { IRREGULAR("Irregular"); @Getter - private String displayString; + private final String displayString; JsonTxType(String displayString) { this.displayString = displayString; diff --git a/core/src/main/java/bisq/core/dao/node/full/network/FullNodeNetworkService.java b/core/src/main/java/bisq/core/dao/node/full/network/FullNodeNetworkService.java index 640ee94b155..3faf2b8bac9 100644 --- a/core/src/main/java/bisq/core/dao/node/full/network/FullNodeNetworkService.java +++ b/core/src/main/java/bisq/core/dao/node/full/network/FullNodeNetworkService.java @@ -136,51 +136,62 @@ public void onAwakeFromStandby() { @Override public void onMessage(NetworkEnvelope networkEnvelope, Connection connection) { if (networkEnvelope instanceof GetBlocksRequest) { - // We received a GetBlocksRequest from a liteNode - if (!stopped) { - final String uid = connection.getUid(); - if (!getBlocksRequestHandlers.containsKey(uid)) { - GetBlocksRequestHandler requestHandler = new GetBlocksRequestHandler(networkNode, - daoStateService, - new GetBlocksRequestHandler.Listener() { - @Override - public void onComplete() { - getBlocksRequestHandlers.remove(uid); - } - - @Override - public void onFault(String errorMessage, @Nullable Connection connection) { - getBlocksRequestHandlers.remove(uid); - if (!stopped) { - log.trace("GetDataRequestHandler failed.\n\tConnection={}\n\t" + - "ErrorMessage={}", connection, errorMessage); - peerManager.handleConnectionFault(connection); - } else { - log.warn("We have stopped already. We ignore that getDataRequestHandler.handle.onFault call."); - } - } - }); - getBlocksRequestHandlers.put(uid, requestHandler); - requestHandler.onGetBlocksRequest((GetBlocksRequest) networkEnvelope, connection); - } else { - log.warn("We have already a GetDataRequestHandler for that connection started. " + - "We start a cleanup timer if the handler has not closed by itself in between 2 minutes."); - - UserThread.runAfter(() -> { - if (getBlocksRequestHandlers.containsKey(uid)) { - GetBlocksRequestHandler handler = getBlocksRequestHandlers.get(uid); - handler.stop(); - getBlocksRequestHandlers.remove(uid); - } - }, CLEANUP_TIMER); - } - } else { - log.warn("We have stopped already. We ignore that onMessage call."); - } + handleGetBlocksRequest((GetBlocksRequest) networkEnvelope, connection); } else if (networkEnvelope instanceof RepublishGovernanceDataRequest) { - log.warn("We received a RepublishGovernanceDataRequest and re-published all proposalPayloads and " + - "blindVotePayloads to the P2P network."); - missingDataRequestService.reRepublishAllGovernanceData(); + handleRepublishGovernanceDataRequest(); } } + + private void handleGetBlocksRequest(GetBlocksRequest getBlocksRequest, Connection connection) { + if (stopped) { + log.warn("We have stopped already. We ignore that onMessage call."); + return; + } + + String uid = connection.getUid(); + if (getBlocksRequestHandlers.containsKey(uid)) { + log.warn("We have already a GetDataRequestHandler for that connection started. " + + "We start a cleanup timer if the handler has not closed by itself in between 2 minutes."); + + UserThread.runAfter(() -> { + if (getBlocksRequestHandlers.containsKey(uid)) { + GetBlocksRequestHandler handler = getBlocksRequestHandlers.get(uid); + handler.stop(); + getBlocksRequestHandlers.remove(uid); + } + }, CLEANUP_TIMER); + return; + } + + GetBlocksRequestHandler requestHandler = new GetBlocksRequestHandler(networkNode, + daoStateService, + new GetBlocksRequestHandler.Listener() { + @Override + public void onComplete() { + getBlocksRequestHandlers.remove(uid); + } + + @Override + public void onFault(String errorMessage, @Nullable Connection connection) { + getBlocksRequestHandlers.remove(uid); + if (!stopped) { + log.trace("GetDataRequestHandler failed.\n\tConnection={}\n\t" + + "ErrorMessage={}", connection, errorMessage); + if (connection != null) { + peerManager.handleConnectionFault(connection); + } + } else { + log.warn("We have stopped already. We ignore that getDataRequestHandler.handle.onFault call."); + } + } + }); + getBlocksRequestHandlers.put(uid, requestHandler); + requestHandler.onGetBlocksRequest(getBlocksRequest, connection); + } + + private void handleRepublishGovernanceDataRequest() { + log.warn("We received a RepublishGovernanceDataRequest and re-published all proposalPayloads and " + + "blindVotePayloads to the P2P network."); + missingDataRequestService.reRepublishAllGovernanceData(); + } } diff --git a/core/src/main/java/bisq/core/dao/node/full/network/GetBlocksRequestHandler.java b/core/src/main/java/bisq/core/dao/node/full/network/GetBlocksRequestHandler.java index b197970f1a8..dd8d6e92034 100644 --- a/core/src/main/java/bisq/core/dao/node/full/network/GetBlocksRequestHandler.java +++ b/core/src/main/java/bisq/core/dao/node/full/network/GetBlocksRequestHandler.java @@ -49,7 +49,7 @@ */ @Slf4j class GetBlocksRequestHandler { - private static final long TIMEOUT = 120; + private static final long TIMEOUT_MIN = 3; /////////////////////////////////////////////////////////////////////////////////////////// @@ -89,22 +89,28 @@ public GetBlocksRequestHandler(NetworkNode networkNode, DaoStateService daoState // API /////////////////////////////////////////////////////////////////////////////////////////// - public void onGetBlocksRequest(GetBlocksRequest getBlocksRequest, final Connection connection) { + public void onGetBlocksRequest(GetBlocksRequest getBlocksRequest, Connection connection) { + long ts = System.currentTimeMillis(); // We limit number of blocks to 6000 which is about 1.5 month. List blocks = new LinkedList<>(daoStateService.getBlocksFromBlockHeight(getBlocksRequest.getFromBlockHeight(), 6000)); List rawBlocks = blocks.stream().map(RawBlock::fromBlock).collect(Collectors.toList()); GetBlocksResponse getBlocksResponse = new GetBlocksResponse(rawBlocks, getBlocksRequest.getNonce()); - log.info("Received GetBlocksRequest from {} for blocks from height {}", - connection.getPeersNodeAddressOptional(), getBlocksRequest.getFromBlockHeight()); - if (timeoutTimer == null) { - timeoutTimer = UserThread.runAfter(() -> { // setup before sending to avoid race conditions - String errorMessage = "A timeout occurred for getBlocksResponse.requestNonce:" + - getBlocksResponse.getRequestNonce() + - " on connection:" + connection; - handleFault(errorMessage, CloseConnectionReason.SEND_MSG_TIMEOUT, connection); - }, - TIMEOUT, TimeUnit.SECONDS); + log.info("Received GetBlocksRequest from {} for blocks from height {}. " + + "Building GetBlocksResponse with {} blocks took {} ms.", + connection.getPeersNodeAddressOptional(), getBlocksRequest.getFromBlockHeight(), + rawBlocks.size(), System.currentTimeMillis() - ts); + + if (timeoutTimer != null) { + timeoutTimer.stop(); + log.warn("Timeout was already running. We stopped it."); } + timeoutTimer = UserThread.runAfter(() -> { // setup before sending to avoid race conditions + String errorMessage = "A timeout occurred for getBlocksResponse.requestNonce:" + + getBlocksResponse.getRequestNonce() + + " on connection: " + connection; + handleFault(errorMessage, CloseConnectionReason.SEND_MSG_TIMEOUT, connection); + }, + TIMEOUT_MIN, TimeUnit.MINUTES); SettableFuture future = networkNode.sendMessage(connection, getBlocksResponse); Futures.addCallback(future, new FutureCallback<>() { @@ -145,7 +151,7 @@ public void stop() { private void handleFault(String errorMessage, CloseConnectionReason closeConnectionReason, Connection connection) { if (!stopped) { - log.debug(errorMessage + "\n\tcloseConnectionReason=" + closeConnectionReason); + log.warn("{}, closeConnectionReason={}", errorMessage, closeConnectionReason); cleanup(); listener.onFault(errorMessage, connection); } else { diff --git a/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java b/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java index a51c5a11235..c0c8b64980c 100644 --- a/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java +++ b/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java @@ -17,6 +17,7 @@ package bisq.core.dao.node.lite; +import bisq.core.btc.setup.WalletsSetup; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.dao.node.BsqNode; import bisq.core.dao.node.explorer.ExportJsonFilesService; @@ -37,6 +38,8 @@ import com.google.inject.Inject; +import javafx.beans.value.ChangeListener; + import java.util.ArrayList; import java.util.List; @@ -54,7 +57,9 @@ public class LiteNode extends BsqNode { private final LiteNodeNetworkService liteNodeNetworkService; private final BsqWalletService bsqWalletService; + private final WalletsSetup walletsSetup; private Timer checkForBlockReceivedTimer; + private final ChangeListener blockDownloadListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -69,11 +74,19 @@ public LiteNode(BlockParser blockParser, P2PService p2PService, LiteNodeNetworkService liteNodeNetworkService, BsqWalletService bsqWalletService, + WalletsSetup walletsSetup, ExportJsonFilesService exportJsonFilesService) { super(blockParser, daoStateService, daoStateSnapshotService, p2PService, exportJsonFilesService); this.liteNodeNetworkService = liteNodeNetworkService; this.bsqWalletService = bsqWalletService; + this.walletsSetup = walletsSetup; + + blockDownloadListener = (observable, oldValue, newValue) -> { + if ((double) newValue == 1) { + setupWalletBestBlockListener(); + } + }; } @@ -87,7 +100,18 @@ public void start() { liteNodeNetworkService.start(); - bsqWalletService.addNewBestBlockListener(block -> { + // We wait until the wallet is synced before using it for triggering requests + if (walletsSetup.isDownloadComplete()) { + setupWalletBestBlockListener(); + } else { + walletsSetup.downloadPercentageProperty().addListener(blockDownloadListener); + } + } + + private void setupWalletBestBlockListener() { + walletsSetup.downloadPercentageProperty().removeListener(blockDownloadListener); + + bsqWalletService.addNewBestBlockListener(blockFromWallet -> { // Check if we are done with parsing if (!daoStateService.isParseBlockChainComplete()) return; @@ -97,18 +121,18 @@ public void start() { checkForBlockReceivedTimer.stop(); } - int height = block.getHeight(); - log.info("New block at height {} from bsqWalletService", height); + int walletBlockHeight = blockFromWallet.getHeight(); + log.info("New block at height {} from bsqWalletService", walletBlockHeight); // We expect to receive the new BSQ block from the network shortly after BitcoinJ has been aware of it. // If we don't receive it we request it manually from seed nodes checkForBlockReceivedTimer = UserThread.runAfter(() -> { - int chainHeight = daoStateService.getChainHeight(); - if (chainHeight < height) { - log.warn("We did not receive a block from the network {} seconds after we saw the new block in BicoinJ. " + + int daoChainHeight = daoStateService.getChainHeight(); + if (daoChainHeight < walletBlockHeight) { + log.warn("We did not receive a block from the network {} seconds after we saw the new block in BitcoinJ. " + "We request from our seed nodes missing blocks from block height {}.", - CHECK_FOR_BLOCK_RECEIVED_DELAY_SEC, chainHeight + 1); - liteNodeNetworkService.requestBlocks(chainHeight + 1); + CHECK_FOR_BLOCK_RECEIVED_DELAY_SEC, daoChainHeight + 1); + liteNodeNetworkService.requestBlocks(daoChainHeight + 1); } }, CHECK_FOR_BLOCK_RECEIVED_DELAY_SEC); }); @@ -157,7 +181,6 @@ public void onFault(String errorMessage, @Nullable Connection connection) { // First we request the blocks from a full node @Override protected void startParseBlocks() { - log.info("startParseBlocks"); liteNodeNetworkService.requestBlocks(getStartBlockHeight()); } @@ -199,8 +222,12 @@ private void onRequestedBlocksReceived(List blockList, Runnable onPars runDelayedBatchProcessing(new ArrayList<>(blockList), () -> { - log.debug("Parsing {} blocks took {} seconds.", blockList.size(), (System.currentTimeMillis() - ts) / 1000d); - if (daoStateService.getChainHeight() < bsqWalletService.getBestChainHeight()) { + log.info("runDelayedBatchProcessing Parsing {} blocks took {} seconds.", blockList.size(), + (System.currentTimeMillis() - ts) / 1000d); + // We only request again if wallet is synced, otherwise we would get repeated calls we want to avoid. + // We deal with that case at the setupWalletBestBlockListener method above. + if (walletsSetup.isDownloadComplete() && + daoStateService.getChainHeight() < bsqWalletService.getBestChainHeight()) { liteNodeNetworkService.requestBlocks(getStartBlockHeight()); } else { onParsingComplete.run(); @@ -229,11 +256,13 @@ private void runDelayedBatchProcessing(List blocks, Runnable resultHan // We received a new block private void onNewBlockReceived(RawBlock block) { int blockHeight = block.getHeight(); - log.debug("onNewBlockReceived: block at height {}, hash={}", blockHeight, block.getHash()); + log.info("onNewBlockReceived: block at height {}, hash={}. Our DAO chainHeight={}", + blockHeight, block.getHash(), chainTipHeight); // We only update chainTipHeight if we get a newer block - if (blockHeight > chainTipHeight) + if (blockHeight > chainTipHeight) { chainTipHeight = blockHeight; + } try { doParseBlock(block); diff --git a/core/src/main/java/bisq/core/dao/node/lite/network/LiteNodeNetworkService.java b/core/src/main/java/bisq/core/dao/node/lite/network/LiteNodeNetworkService.java index 0b40e80b96c..f13d99aa8b4 100644 --- a/core/src/main/java/bisq/core/dao/node/lite/network/LiteNodeNetworkService.java +++ b/core/src/main/java/bisq/core/dao/node/lite/network/LiteNodeNetworkService.java @@ -99,7 +99,7 @@ public interface Listener { private final Map, RequestBlocksHandler> requestBlocksHandlerMap = new HashMap<>(); private Timer retryTimer; private boolean stopped; - private Set receivedBlocks = new HashSet<>(); + private final Set receivedBlocks = new HashSet<>(); /////////////////////////////////////////////////////////////////////////////////////////// @@ -129,7 +129,6 @@ public void start() { peerManager.addListener(this); } - @SuppressWarnings("Duplicates") public void shutDown() { stopped = true; stopRetryTimer(); @@ -152,19 +151,21 @@ public void requestBlocks(int startBlockHeight) { Optional connectionToSeedNodeOptional = networkNode.getConfirmedConnections().stream() .filter(peerManager::isSeedNode) .findAny(); - if (connectionToSeedNodeOptional.isPresent() && - connectionToSeedNodeOptional.get().getPeersNodeAddressOptional().isPresent()) { - requestBlocks(connectionToSeedNodeOptional.get().getPeersNodeAddressOptional().get(), startBlockHeight); - } else { - tryWithNewSeedNode(startBlockHeight); - } + + connectionToSeedNodeOptional.flatMap(Connection::getPeersNodeAddressOptional) + .ifPresentOrElse(candidate -> { + seedNodeAddresses.remove(candidate); + requestBlocks(candidate, startBlockHeight); + }, () -> { + tryWithNewSeedNode(startBlockHeight); + }); } public void reset() { lastRequestedBlockHeight = 0; lastReceivedBlockHeight = 0; retryCounter = 0; - requestBlocksHandlerMap.values().forEach(RequestBlocksHandler::cancel); + requestBlocksHandlerMap.values().forEach(RequestBlocksHandler::terminate); } @@ -202,7 +203,6 @@ public void onAllConnectionsLost() { closeAllHandlers(); stopRetryTimer(); stopped = true; - tryWithNewSeedNode(lastRequestedBlockHeight); } @@ -218,8 +218,7 @@ public void onAwakeFromStandby() { log.info("onAwakeFromStandby"); closeAllHandlers(); stopped = false; - if (!networkNode.getAllConnections().isEmpty()) - tryWithNewSeedNode(lastRequestedBlockHeight); + tryWithNewSeedNode(lastRequestedBlockHeight); } @@ -232,17 +231,20 @@ public void onMessage(NetworkEnvelope networkEnvelope, Connection connection) { if (networkEnvelope instanceof NewBlockBroadcastMessage) { NewBlockBroadcastMessage newBlockBroadcastMessage = (NewBlockBroadcastMessage) networkEnvelope; // We combine blockHash and txId list in case we receive blocks with different transactions. - List txIds = newBlockBroadcastMessage.getBlock().getRawTxs().stream().map(BaseTx::getId).collect(Collectors.toList()); - String extBlockId = newBlockBroadcastMessage.getBlock().getHash() + ":" + txIds; - if (!receivedBlocks.contains(extBlockId)) { - log.debug("We received a new message from peer {} and broadcast it to our peers. extBlockId={}", - connection.getPeersNodeAddressOptional().orElse(null), extBlockId); - receivedBlocks.add(extBlockId); - broadcaster.broadcast(newBlockBroadcastMessage, connection.getPeersNodeAddressOptional().orElse(null)); - listeners.forEach(listener -> listener.onNewBlockReceived(newBlockBroadcastMessage)); - } else { - log.debug("We had that message already and do not further broadcast it. extBlockId={}", extBlockId); + List txIds = newBlockBroadcastMessage.getBlock().getRawTxs().stream() + .map(BaseTx::getId) + .collect(Collectors.toList()); + String blockUid = newBlockBroadcastMessage.getBlock().getHash() + ":" + txIds; + if (receivedBlocks.contains(blockUid)) { + log.debug("We had that message already and do not further broadcast it. blockUid={}", blockUid); + return; } + + log.info("We received a NewBlockBroadcastMessage from peer {} and broadcast it to our peers. blockUid={}", + connection.getPeersNodeAddressOptional().orElse(null), blockUid); + receivedBlocks.add(blockUid); + broadcaster.broadcast(newBlockBroadcastMessage, connection.getPeersNodeAddressOptional().orElse(null)); + listeners.forEach(listener -> listener.onNewBlockReceived(newBlockBroadcastMessage)); } } @@ -252,78 +254,85 @@ public void onMessage(NetworkEnvelope networkEnvelope, Connection connection) { /////////////////////////////////////////////////////////////////////////////////////////// private void requestBlocks(NodeAddress peersNodeAddress, int startBlockHeight) { - if (!stopped) { - final Tuple2 key = new Tuple2<>(peersNodeAddress, startBlockHeight); - if (!requestBlocksHandlerMap.containsKey(key)) { - if (startBlockHeight >= lastReceivedBlockHeight) { - RequestBlocksHandler requestBlocksHandler = new RequestBlocksHandler(networkNode, - peerManager, - peersNodeAddress, - startBlockHeight, - new RequestBlocksHandler.Listener() { - @Override - public void onComplete(GetBlocksResponse getBlocksResponse) { - log.debug("requestBlocksHandler of outbound connection complete. nodeAddress={}", - peersNodeAddress); - stopRetryTimer(); - - // need to remove before listeners are notified as they cause the update call - requestBlocksHandlerMap.remove(key); - // we only notify if our request was latest - if (startBlockHeight >= lastReceivedBlockHeight) { - lastReceivedBlockHeight = startBlockHeight; - - listeners.forEach(listener -> listener.onRequestedBlocksReceived(getBlocksResponse, - () -> { - // After we received the blocks we allow to disconnect seed nodes. - // We delay 20 seconds to allow multiple requests to finish. - UserThread.runAfter(() -> peerManager.setAllowDisconnectSeedNodes(true), 20); - })); - } else { - log.warn("We got a response which is already obsolete because we receive a " + - "response from a request with a higher block height. " + - "This could theoretically happen, but is very unlikely."); - } - } - - @Override - public void onFault(String errorMessage, @Nullable Connection connection) { - log.warn("requestBlocksHandler with outbound connection failed.\n\tnodeAddress={}\n\t" + - "ErrorMessage={}", peersNodeAddress, errorMessage); - - peerManager.handleConnectionFault(peersNodeAddress); - requestBlocksHandlerMap.remove(key); - - listeners.forEach(listener -> listener.onFault(errorMessage, connection)); - - tryWithNewSeedNode(startBlockHeight); - } - }); - requestBlocksHandlerMap.put(key, requestBlocksHandler); - log.info("requestBlocks with startBlockHeight={} from peer {}", startBlockHeight, peersNodeAddress); - requestBlocksHandler.requestBlocks(); - } else { - log.warn("startBlockHeight must not be smaller than lastReceivedBlockHeight. That should never happen." + - "startBlockHeight={},lastReceivedBlockHeight={}", startBlockHeight, lastReceivedBlockHeight); - DevEnv.logErrorAndThrowIfDevMode("startBlockHeight must be larger than lastReceivedBlockHeight. startBlockHeight=" + - startBlockHeight + " / lastReceivedBlockHeight=" + lastReceivedBlockHeight); + if (stopped) { + log.warn("We have stopped already. We ignore that requestData call."); + return; + } + + Tuple2 key = new Tuple2<>(peersNodeAddress, startBlockHeight); + if (requestBlocksHandlerMap.containsKey(key)) { + log.warn("We have started already a requestDataHandshake for startBlockHeight {} to peer. nodeAddress={}\n" + + "We start a cleanup timer if the handler has not closed by itself in between 2 minutes.", + peersNodeAddress, startBlockHeight); + + UserThread.runAfter(() -> { + if (requestBlocksHandlerMap.containsKey(key)) { + RequestBlocksHandler handler = requestBlocksHandlerMap.get(key); + handler.terminate(); + requestBlocksHandlerMap.remove(key); } - } else { - log.warn("We have started already a requestDataHandshake for startBlockHeight {} to peer. nodeAddress={}\n" + - "We start a cleanup timer if the handler has not closed by itself in between 2 minutes.", - peersNodeAddress, startBlockHeight); - - UserThread.runAfter(() -> { - if (requestBlocksHandlerMap.containsKey(key)) { - RequestBlocksHandler handler = requestBlocksHandlerMap.get(key); - handler.stop(); + }, CLEANUP_TIMER); + return; + } + + if (startBlockHeight < lastReceivedBlockHeight) { + log.warn("startBlockHeight must not be smaller than lastReceivedBlockHeight. That should never happen." + + "startBlockHeight={},lastReceivedBlockHeight={}", startBlockHeight, lastReceivedBlockHeight); + DevEnv.logErrorAndThrowIfDevMode("startBlockHeight must be larger than lastReceivedBlockHeight. startBlockHeight=" + + startBlockHeight + " / lastReceivedBlockHeight=" + lastReceivedBlockHeight); + return; + } + + // In case we would have had an earlier request and had set allowDisconnectSeedNodes to true we un-do that + // if we get a repeated request. + peerManager.setAllowDisconnectSeedNodes(false); + RequestBlocksHandler requestBlocksHandler = new RequestBlocksHandler(networkNode, + peerManager, + peersNodeAddress, + startBlockHeight, + new RequestBlocksHandler.Listener() { + @Override + public void onComplete(GetBlocksResponse getBlocksResponse) { + log.info("requestBlocksHandler to {} completed", peersNodeAddress); + stopRetryTimer(); + + // need to remove before listeners are notified as they cause the update call requestBlocksHandlerMap.remove(key); + // we only notify if our request was latest + if (startBlockHeight >= lastReceivedBlockHeight) { + lastReceivedBlockHeight = startBlockHeight; + + listeners.forEach(listener -> listener.onRequestedBlocksReceived(getBlocksResponse, + () -> { + // After we received the blocks we allow to disconnect seed nodes. + // We delay 20 seconds to allow multiple requests to finish. + UserThread.runAfter(() -> peerManager.setAllowDisconnectSeedNodes(true), 20); + })); + } else { + log.warn("We got a response which is already obsolete because we received a " + + "response from a request with a higher block height. " + + "This could theoretically happen, but is very unlikely."); + } } - }, CLEANUP_TIMER); - } - } else { - log.warn("We have stopped already. We ignore that requestData call."); - } + + @Override + public void onFault(String errorMessage, @Nullable Connection connection) { + log.warn("requestBlocksHandler with outbound connection failed.\n\tnodeAddress={}\n\t" + + "ErrorMessage={}", peersNodeAddress, errorMessage); + + peerManager.handleConnectionFault(peersNodeAddress); + requestBlocksHandlerMap.remove(key); + + listeners.forEach(listener -> listener.onFault(errorMessage, connection)); + + // We allow now to disconnect from that seed. + peerManager.setAllowDisconnectSeedNodes(true); + + tryWithNewSeedNode(startBlockHeight); + } + }); + requestBlocksHandlerMap.put(key, requestBlocksHandler); + requestBlocksHandler.requestBlocks(); } @@ -332,37 +341,52 @@ public void onFault(String errorMessage, @Nullable Connection connection) { /////////////////////////////////////////////////////////////////////////////////////////// private void tryWithNewSeedNode(int startBlockHeight) { - if (retryTimer == null) { - retryCounter++; - if (retryCounter <= MAX_RETRY) { - retryTimer = UserThread.runAfter(() -> { - stopped = false; - - stopRetryTimer(); - - List list = seedNodeAddresses.stream() - .filter(e -> peerManager.isSeedNode(e) && !peerManager.isSelf(e)) - .collect(Collectors.toList()); - Collections.shuffle(list); - - if (!list.isEmpty()) { - NodeAddress nextCandidate = list.get(0); - seedNodeAddresses.remove(nextCandidate); - log.info("We try requestBlocks with {}", nextCandidate); - requestBlocks(nextCandidate, startBlockHeight); - } else { - log.warn("No more seed nodes available we could try."); - listeners.forEach(Listener::onNoSeedNodeAvailable); - } - }, - RETRY_DELAY_SEC); - } else { - log.warn("We tried {} times but could not connect to a seed node.", retryCounter); - listeners.forEach(Listener::onNoSeedNodeAvailable); - } - } else { + if (networkNode.getAllConnections().isEmpty()) { + return; + } + + if (lastRequestedBlockHeight == 0) { + return; + } + + if (stopped) { + return; + } + + if (retryTimer != null) { log.warn("We have a retry timer already running."); + return; + } + + retryCounter++; + + if (retryCounter > MAX_RETRY) { + log.warn("We tried {} times but could not connect to a seed node.", retryCounter); + listeners.forEach(Listener::onNoSeedNodeAvailable); + return; } + + retryTimer = UserThread.runAfter(() -> { + stopped = false; + + stopRetryTimer(); + + List list = seedNodeAddresses.stream() + .filter(e -> peerManager.isSeedNode(e) && !peerManager.isSelf(e)) + .collect(Collectors.toList()); + Collections.shuffle(list); + + if (!list.isEmpty()) { + NodeAddress nextCandidate = list.get(0); + seedNodeAddresses.remove(nextCandidate); + log.info("We try requestBlocks from {} with startBlockHeight={}", nextCandidate, startBlockHeight); + requestBlocks(nextCandidate, startBlockHeight); + } else { + log.warn("No more seed nodes available we could try."); + listeners.forEach(Listener::onNoSeedNodeAvailable); + } + }, + RETRY_DELAY_SEC); } private void stopRetryTimer() { @@ -386,17 +410,14 @@ private void removeFromRequestBlocksHandlerMap(NodeAddress nodeAddress) { requestBlocksHandlerMap.entrySet().stream() .filter(e -> e.getKey().first.equals(nodeAddress)) .findAny() - .map(Map.Entry::getValue) - .ifPresent(handler -> { - final Tuple2 key = new Tuple2<>(handler.getNodeAddress(), handler.getStartBlockHeight()); - requestBlocksHandlerMap.get(key).cancel(); - requestBlocksHandlerMap.remove(key); + .ifPresent(e -> { + e.getValue().terminate(); + requestBlocksHandlerMap.remove(e.getKey()); }); } - private void closeAllHandlers() { - requestBlocksHandlerMap.values().forEach(RequestBlocksHandler::cancel); + requestBlocksHandlerMap.values().forEach(RequestBlocksHandler::terminate); requestBlocksHandlerMap.clear(); } } diff --git a/core/src/main/java/bisq/core/dao/node/lite/network/RequestBlocksHandler.java b/core/src/main/java/bisq/core/dao/node/lite/network/RequestBlocksHandler.java index 60374ffd7da..752e4829f87 100644 --- a/core/src/main/java/bisq/core/dao/node/lite/network/RequestBlocksHandler.java +++ b/core/src/main/java/bisq/core/dao/node/lite/network/RequestBlocksHandler.java @@ -36,7 +36,9 @@ import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.SettableFuture; +import java.util.Optional; import java.util.Random; +import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -44,14 +46,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.google.common.base.Preconditions.checkArgument; - /** * Sends a GetBlocksRequest to a full node and listens on corresponding GetBlocksResponse from the full node. */ @Slf4j public class RequestBlocksHandler implements MessageListener { - private static final long TIMEOUT = 120; + private static final long TIMEOUT_MIN = 3; /////////////////////////////////////////////////////////////////////////////////////////// @@ -98,66 +98,61 @@ public RequestBlocksHandler(NetworkNode networkNode, this.listener = listener; } - public void cancel() { - cleanup(); - } - /////////////////////////////////////////////////////////////////////////////////////////// // API /////////////////////////////////////////////////////////////////////////////////////////// public void requestBlocks() { - if (!stopped) { - GetBlocksRequest getBlocksRequest = new GetBlocksRequest(startBlockHeight, nonce, networkNode.getNodeAddress()); - log.debug("getBlocksRequest " + getBlocksRequest); - if (timeoutTimer == null) { - timeoutTimer = UserThread.runAfter(() -> { // setup before sending to avoid race conditions - if (!stopped) { - String errorMessage = "A timeout occurred when sending getBlocksRequest:" + getBlocksRequest + - " on peersNodeAddress:" + nodeAddress; - log.debug(errorMessage + " / RequestDataHandler=" + RequestBlocksHandler.this); - handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_TIMEOUT); - } else { - log.trace("We have stopped already. We ignore that timeoutTimer.run call. " + - "Might be caused by an previous networkNode.sendMessage.onFailure."); - } - }, - TIMEOUT); - } + if (stopped) { + log.warn("We have stopped already. We ignore that requestData call."); + return; + } - log.info("We request blocks from peer {} from block height {}.", nodeAddress, getBlocksRequest.getFromBlockHeight()); - networkNode.addMessageListener(this); - SettableFuture future = networkNode.sendMessage(nodeAddress, getBlocksRequest); - Futures.addCallback(future, new FutureCallback<>() { - @Override - public void onSuccess(Connection connection) { - if (!stopped) { - log.info("Sending of GetBlocksRequest message to peer {} succeeded.", nodeAddress.getFullAddress()); - } else { - log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call." + - "Might be caused by a previous timeout."); - } - } + GetBlocksRequest getBlocksRequest = new GetBlocksRequest(startBlockHeight, nonce, networkNode.getNodeAddress()); - @Override - public void onFailure(@NotNull Throwable throwable) { + if (timeoutTimer != null) { + log.warn("We had a timer already running and stop it."); + timeoutTimer.stop(); + } + timeoutTimer = UserThread.runAfter(() -> { // setup before sending to avoid race conditions if (!stopped) { - String errorMessage = "Sending getBlocksRequest to " + nodeAddress + - " failed. That is expected if the peer is offline.\n\t" + - "getBlocksRequest=" + getBlocksRequest + "." + - "\n\tException=" + throwable.getMessage(); - log.error(errorMessage); - handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_FAILURE); + String errorMessage = "A timeout occurred when sending getBlocksRequest:" + getBlocksRequest + + " on peersNodeAddress:" + nodeAddress; + log.debug("{} / RequestDataHandler={}", errorMessage, RequestBlocksHandler.this); + handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_TIMEOUT); } else { - log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call. " + - "Might be caused by a previous timeout."); + log.warn("We have stopped already. We ignore that timeoutTimer.run call. " + + "Might be caused by a previous networkNode.sendMessage.onFailure."); } + }, + TIMEOUT_MIN, TimeUnit.MINUTES); + + log.info("We request blocks from peer {} from block height {}.", nodeAddress, getBlocksRequest.getFromBlockHeight()); + + networkNode.addMessageListener(this); + + SettableFuture future = networkNode.sendMessage(nodeAddress, getBlocksRequest); + Futures.addCallback(future, new FutureCallback<>() { + @Override + public void onSuccess(Connection connection) { + log.info("Sending of GetBlocksRequest message to peer {} succeeded.", nodeAddress.getFullAddress()); + } + + @Override + public void onFailure(@NotNull Throwable throwable) { + if (!stopped) { + String errorMessage = "Sending getBlocksRequest to " + nodeAddress + + " failed. That is expected if the peer is offline.\n\t" + + "getBlocksRequest=" + getBlocksRequest + "." + + "\n\tException=" + throwable.getMessage(); + log.error(errorMessage); + handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_FAILURE); + } else { + log.warn("We have stopped already. We ignore that networkNode.sendMessage.onFailure call."); } - }, MoreExecutors.directExecutor()); - } else { - log.warn("We have stopped already. We ignore that requestData call."); - } + } + }, MoreExecutors.directExecutor()); } @@ -168,56 +163,60 @@ public void onFailure(@NotNull Throwable throwable) { @Override public void onMessage(NetworkEnvelope networkEnvelope, Connection connection) { if (networkEnvelope instanceof GetBlocksResponse) { - if (connection.getPeersNodeAddressOptional().isPresent() && connection.getPeersNodeAddressOptional().get().equals(nodeAddress)) { - if (!stopped) { - GetBlocksResponse getBlocksResponse = (GetBlocksResponse) networkEnvelope; - if (getBlocksResponse.getRequestNonce() == nonce) { - stopTimeoutTimer(); - checkArgument(connection.getPeersNodeAddressOptional().isPresent(), - "RequestDataHandler.onMessage: connection.getPeersNodeAddressOptional() must be present " + - "at that moment"); - cleanup(); - log.info("We received from peer {} a BlocksResponse with {} blocks", - nodeAddress.getFullAddress(), getBlocksResponse.getBlocks().size()); - listener.onComplete(getBlocksResponse); - } else { - log.warn("Nonce not matching. That can happen rarely if we get a response after a canceled " + - "handshake (timeout causes connection close but peer might have sent a msg before " + - "connection was closed).\n\t" + - "We drop that message. nonce={} / requestNonce={}", - nonce, getBlocksResponse.getRequestNonce()); - } - } else { - log.warn("We have stopped already. We ignore that onDataRequest call."); - } - } else { - log.warn("We got a message from ourselves. That should never happen."); + if (stopped) { + log.warn("We have stopped already. We ignore that onDataRequest call."); + return; + } + + Optional optionalNodeAddress = connection.getPeersNodeAddressOptional(); + if (!optionalNodeAddress.isPresent()) { + log.warn("Peers node address is not present, that is not expected."); + // We do not return here as in case the connection has been created from the peers side we might not + // have the address set. As we check the nonce later we do not care that much for the check if the + // connection address is the same as the one we used. + } else if (!optionalNodeAddress.get().equals(nodeAddress)) { + log.warn("Peers node address is not the same we used for the request. This is not expected. We ignore that message."); + return; + } + + GetBlocksResponse getBlocksResponse = (GetBlocksResponse) networkEnvelope; + if (getBlocksResponse.getRequestNonce() != nonce) { + log.warn("Nonce not matching. That can happen rarely if we get a response after a canceled " + + "handshake (timeout causes connection close but peer might have sent a msg before " + + "connection was closed).\n\t" + + "We drop that message. nonce={} / requestNonce={}", + nonce, getBlocksResponse.getRequestNonce()); + return; } + + terminate(); + log.info("We received from peer {} a BlocksResponse with {} blocks", + nodeAddress.getFullAddress(), getBlocksResponse.getBlocks().size()); + listener.onComplete(getBlocksResponse); } } - public void stop() { - cleanup(); + public void terminate() { + stopped = true; + networkNode.removeMessageListener(this); + stopTimeoutTimer(); } + /////////////////////////////////////////////////////////////////////////////////////////// // Private /////////////////////////////////////////////////////////////////////////////////////////// @SuppressWarnings("UnusedParameters") - private void handleFault(String errorMessage, NodeAddress nodeAddress, CloseConnectionReason closeConnectionReason) { - cleanup(); + private void handleFault(String errorMessage, + NodeAddress nodeAddress, + CloseConnectionReason closeConnectionReason) { + terminate(); peerManager.handleConnectionFault(nodeAddress); listener.onFault(errorMessage, null); } - private void cleanup() { - stopped = true; - networkNode.removeMessageListener(this); - stopTimeoutTimer(); - } - private void stopTimeoutTimer() { if (timeoutTimer != null) { timeoutTimer.stop(); diff --git a/core/src/main/java/bisq/core/dao/node/parser/TempTx.java b/core/src/main/java/bisq/core/dao/node/parser/TempTx.java index e7bac4d2e34..b98d2f4579b 100644 --- a/core/src/main/java/bisq/core/dao/node/parser/TempTx.java +++ b/core/src/main/java/bisq/core/dao/node/parser/TempTx.java @@ -27,7 +27,8 @@ import java.util.Objects; import java.util.stream.Collectors; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import javax.annotation.Nullable; @@ -36,7 +37,8 @@ * After parsing it will get cloned to the immutable Tx. * We don't need to implement the ProtoBuffer methods as it is not persisted or sent over the wire. */ -@Data +@Getter +@Setter public class TempTx extends BaseTx { static TempTx fromRawTx(RawTx rawTx) { return new TempTx(rawTx.getTxVersion(), diff --git a/core/src/main/java/bisq/core/dao/node/parser/TempTxOutput.java b/core/src/main/java/bisq/core/dao/node/parser/TempTxOutput.java index 0109dc656fc..8aa78c2b08f 100644 --- a/core/src/main/java/bisq/core/dao/node/parser/TempTxOutput.java +++ b/core/src/main/java/bisq/core/dao/node/parser/TempTxOutput.java @@ -24,7 +24,8 @@ import java.util.Objects; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import javax.annotation.Nullable; @@ -32,7 +33,8 @@ * Contains mutable BSQ specific data (TxOutputType) and used only during tx parsing. * Will get converted to immutable TxOutput after tx parsing is completed. */ -@Data +@Getter +@Setter public class TempTxOutput extends BaseTxOutput { static TempTxOutput fromRawTxOutput(RawTxOutput txOutput) { return new TempTxOutput(txOutput.getIndex(), @@ -78,6 +80,10 @@ private TempTxOutput(int index, this.unlockBlockHeight = unlockBlockHeight; } + public boolean isOpReturnOutput() { + // We do not check for pubKeyScript.scriptType.NULL_DATA because that is only set if dumpBlockchainData is true + return getOpReturnData() != null; + } @Override public String toString() { @@ -88,12 +94,6 @@ public String toString() { "\n} " + super.toString(); } - public boolean isOpReturnOutput() { - // We do not check for pubKeyScript.scriptType.NULL_DATA because that is only set if dumpBlockchainData is true - return getOpReturnData() != null; - } - - // Enums must not be used directly for hashCode or equals as it delivers the Object.hashCode (internal address)! // The equals and hashCode methods cannot be overwritten in Enums. @Override diff --git a/core/src/main/java/bisq/core/dao/node/parser/TxOutputParser.java b/core/src/main/java/bisq/core/dao/node/parser/TxOutputParser.java index cf6815d5283..7f311d64061 100644 --- a/core/src/main/java/bisq/core/dao/node/parser/TxOutputParser.java +++ b/core/src/main/java/bisq/core/dao/node/parser/TxOutputParser.java @@ -87,9 +87,9 @@ */ @Slf4j class TxOutputParser { - private static int ACTIVATE_HARD_FORK_1_HEIGHT_MAINNET = 605000; - private static int ACTIVATE_HARD_FORK_1_HEIGHT_TESTNET = 1583054; - private static int ACTIVATE_HARD_FORK_1_HEIGHT_REGTEST = 1; + private static final int ACTIVATE_HARD_FORK_1_HEIGHT_MAINNET = 605000; + private static final int ACTIVATE_HARD_FORK_1_HEIGHT_TESTNET = 1583054; + private static final int ACTIVATE_HARD_FORK_1_HEIGHT_REGTEST = 1; private final DaoStateService daoStateService; // Setters diff --git a/core/src/main/java/bisq/core/dao/node/parser/exceptions/BlockHashNotConnectingException.java b/core/src/main/java/bisq/core/dao/node/parser/exceptions/BlockHashNotConnectingException.java index 41635a5a17e..c97ee28e111 100644 --- a/core/src/main/java/bisq/core/dao/node/parser/exceptions/BlockHashNotConnectingException.java +++ b/core/src/main/java/bisq/core/dao/node/parser/exceptions/BlockHashNotConnectingException.java @@ -24,7 +24,7 @@ @Getter public class BlockHashNotConnectingException extends Exception { - private RawBlock rawBlock; + private final RawBlock rawBlock; public BlockHashNotConnectingException(RawBlock rawBlock) { this.rawBlock = rawBlock; diff --git a/core/src/main/java/bisq/core/dao/node/parser/exceptions/BlockHeightNotConnectingException.java b/core/src/main/java/bisq/core/dao/node/parser/exceptions/BlockHeightNotConnectingException.java index 875c5b256b2..09b39be6471 100644 --- a/core/src/main/java/bisq/core/dao/node/parser/exceptions/BlockHeightNotConnectingException.java +++ b/core/src/main/java/bisq/core/dao/node/parser/exceptions/BlockHeightNotConnectingException.java @@ -24,7 +24,7 @@ @Getter public class BlockHeightNotConnectingException extends Exception { - private RawBlock rawBlock; + private final RawBlock rawBlock; public BlockHeightNotConnectingException(RawBlock rawBlock) { this.rawBlock = rawBlock; diff --git a/core/src/main/java/bisq/core/dao/node/parser/exceptions/RequiredReorgFromSnapshotException.java b/core/src/main/java/bisq/core/dao/node/parser/exceptions/RequiredReorgFromSnapshotException.java index 59a36c66939..184676078cb 100644 --- a/core/src/main/java/bisq/core/dao/node/parser/exceptions/RequiredReorgFromSnapshotException.java +++ b/core/src/main/java/bisq/core/dao/node/parser/exceptions/RequiredReorgFromSnapshotException.java @@ -24,7 +24,7 @@ @Getter public class RequiredReorgFromSnapshotException extends Exception { - private RawBlock rawBlock; + private final RawBlock rawBlock; public RequiredReorgFromSnapshotException(RawBlock rawBlock) { this.rawBlock = rawBlock; diff --git a/p2p/src/main/java/bisq/network/p2p/peers/getdata/RequestDataHandler.java b/p2p/src/main/java/bisq/network/p2p/peers/getdata/RequestDataHandler.java index e00fdd67bf9..7ad491a09c9 100644 --- a/p2p/src/main/java/bisq/network/p2p/peers/getdata/RequestDataHandler.java +++ b/p2p/src/main/java/bisq/network/p2p/peers/getdata/RequestDataHandler.java @@ -134,7 +134,7 @@ void requestData(NodeAddress nodeAddress, boolean isPreliminaryDataRequest) { handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_TIMEOUT); } else { log.trace("We have stopped already. We ignore that timeoutTimer.run call. " + - "Might be caused by an previous networkNode.sendMessage.onFailure."); + "Might be caused by a previous networkNode.sendMessage.onFailure."); } }, TIMEOUT); @@ -152,7 +152,7 @@ public void onSuccess(Connection connection) { log.trace("Send {} to {} succeeded.", getDataRequest, nodeAddress); } else { log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call." + - "Might be caused by an previous timeout."); + "Might be caused by a previous timeout."); } } @@ -166,7 +166,7 @@ public void onFailure(@NotNull Throwable throwable) { handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_FAILURE); } else { log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call. " + - "Might be caused by an previous timeout."); + "Might be caused by a previous timeout."); } } }, MoreExecutors.directExecutor());