diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 59b70d9459c..d52f38b3e8f 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -180,6 +180,7 @@ diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml index 6e6eec11483..79ee123c2b2 100644 --- a/.idea/codeStyles/codeStyleConfig.xml +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -1,6 +1,5 @@ \ No newline at end of file diff --git a/common/src/main/java/bisq/common/storage/Storage.java b/common/src/main/java/bisq/common/storage/Storage.java index 21e5a89fb76..4d0de66e91f 100644 --- a/common/src/main/java/bisq/common/storage/Storage.java +++ b/common/src/main/java/bisq/common/storage/Storage.java @@ -52,11 +52,7 @@ public class Storage { private static final Logger log = LoggerFactory.getLogger(Storage.class); public static final String STORAGE_DIR = "storageDir"; - private static CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler; - - public static void setCorruptedDatabaseFilesHandler(CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) { - Storage.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler; - } + private final CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler; private final File dir; private FileManager fileManager; @@ -72,9 +68,12 @@ public static void setCorruptedDatabaseFilesHandler(CorruptedDatabaseFilesHandle /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public Storage(@Named(STORAGE_DIR) File dir, PersistenceProtoResolver persistenceProtoResolver) { + public Storage(@Named(STORAGE_DIR) File dir, + PersistenceProtoResolver persistenceProtoResolver, + CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) { this.dir = dir; this.persistenceProtoResolver = persistenceProtoResolver; + this.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler; } @Nullable diff --git a/core/src/main/java/bisq/core/app/BisqExecutable.java b/core/src/main/java/bisq/core/app/BisqExecutable.java index 89a9e865c8d..b88423c7bfb 100644 --- a/core/src/main/java/bisq/core/app/BisqExecutable.java +++ b/core/src/main/java/bisq/core/app/BisqExecutable.java @@ -42,8 +42,6 @@ import bisq.common.handlers.ResultHandler; import bisq.common.proto.persistable.PersistedDataHost; import bisq.common.setup.GracefulShutDownHandler; -import bisq.common.storage.CorruptedDatabaseFilesHandler; -import bisq.common.storage.Storage; import org.springframework.core.env.JOptCommandLinePropertySource; @@ -232,8 +230,6 @@ protected Injector getInjector() { protected void applyInjector() { setupDevEnv(); - setCorruptedDataBaseFilesHandler(); - setupPersistedDataHosts(injector); } @@ -242,11 +238,6 @@ protected void setupDevEnv() { DevEnv.setDaoActivated(BisqEnvironment.isDaoActivated(bisqEnvironment)); } - private void setCorruptedDataBaseFilesHandler() { - CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler = injector.getInstance(CorruptedDatabaseFilesHandler.class); - Storage.setCorruptedDatabaseFilesHandler(corruptedDatabaseFilesHandler); - } - protected void setupPersistedDataHosts(Injector injector) { try { PersistedDataHost.apply(CorePersistedDataHost.getPersistedDataHosts(injector)); diff --git a/core/src/main/java/bisq/core/arbitration/DisputeManager.java b/core/src/main/java/bisq/core/arbitration/DisputeManager.java index ed1a665bd5d..ca38c0ac7a7 100644 --- a/core/src/main/java/bisq/core/arbitration/DisputeManager.java +++ b/core/src/main/java/bisq/core/arbitration/DisputeManager.java @@ -56,7 +56,6 @@ import bisq.common.handlers.ResultHandler; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.proto.persistable.PersistedDataHost; -import bisq.common.proto.persistable.PersistenceProtoResolver; import bisq.common.storage.Storage; import bisq.common.util.Tuple2; @@ -66,8 +65,6 @@ import com.google.inject.Inject; -import javax.inject.Named; - import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; @@ -77,8 +74,6 @@ import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; -import java.io.File; - import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -136,8 +131,7 @@ public DisputeManager(P2PService p2PService, ClosedTradableManager closedTradableManager, OpenOfferManager openOfferManager, KeyRing keyRing, - PersistenceProtoResolver persistenceProtoResolver, - @Named(Storage.STORAGE_DIR) File storageDir) { + Storage storage) { this.p2PService = p2PService; this.tradeWalletService = tradeWalletService; this.walletService = walletService; @@ -147,7 +141,7 @@ public DisputeManager(P2PService p2PService, this.openOfferManager = openOfferManager; this.keyRing = keyRing; - disputeStorage = new Storage<>(storageDir, persistenceProtoResolver); + disputeStorage = storage; openDisputes = new HashMap<>(); closedDisputes = new HashMap<>(); @@ -207,7 +201,8 @@ public void onUpdatedDataReceived() { onDisputesChangeListener(disputes.getList(), null); } - private void onDisputesChangeListener(List addedList, @Nullable List removedList) { + private void onDisputesChangeListener(List addedList, + @Nullable List removedList) { if (removedList != null) { removedList.forEach(dispute -> { String id = dispute.getId(); @@ -295,7 +290,8 @@ private void applyMessages() { decryptedMailboxMessageWithPubKeys.clear(); } - private void processAckMessage(AckMessage ackMessage, @Nullable DecryptedMessageWithPubKey decryptedMessageWithPubKey) { + private void processAckMessage(AckMessage ackMessage, + @Nullable DecryptedMessageWithPubKey decryptedMessageWithPubKey) { if (ackMessage.getSourceType() == AckMessageSourceType.DISPUTE_MESSAGE) { if (ackMessage.isSuccess()) { log.info("Received AckMessage for {} with tradeId {} and uid {}", @@ -339,7 +335,10 @@ else if (message instanceof PeerPublishedDisputePayoutTxMessage) log.warn("Unsupported message at dispatchMessage.\nmessage=" + message); } - public void sendOpenNewDisputeMessage(Dispute dispute, boolean reOpen, ResultHandler resultHandler, FaultHandler faultHandler) { + public void sendOpenNewDisputeMessage(Dispute dispute, + boolean reOpen, + ResultHandler resultHandler, + FaultHandler faultHandler) { if (!disputes.contains(dispute)) { final Optional storedDisputeOptional = findDispute(dispute.getTradeId(), dispute.getTraderId()); if (!storedDisputeOptional.isPresent() || reOpen) { @@ -433,7 +432,9 @@ public void onFault(String errorMessage) { } // arbitrator sends that to trading peer when he received openDispute request - private String sendPeerOpenedDisputeMessage(Dispute disputeFromOpener, Contract contractFromOpener, PubKeyRing pubKeyRing) { + private String sendPeerOpenedDisputeMessage(Dispute disputeFromOpener, + Contract contractFromOpener, + PubKeyRing pubKeyRing) { Dispute dispute = new Dispute( disputeStorage, disputeFromOpener.getTradeId(), @@ -539,7 +540,9 @@ public void onFault(String errorMessage) { } // traders send msg to the arbitrator or arbitrator to 1 trader (trader to trader is not allowed) - public DisputeCommunicationMessage sendDisputeDirectMessage(Dispute dispute, String text, ArrayList attachments) { + public DisputeCommunicationMessage sendDisputeDirectMessage(Dispute dispute, + String text, + ArrayList attachments) { DisputeCommunicationMessage message = new DisputeCommunicationMessage( dispute.getTradeId(), dispute.getTraderPubKeyRing().hashCode(), diff --git a/core/src/main/java/bisq/core/offer/OpenOfferManager.java b/core/src/main/java/bisq/core/offer/OpenOfferManager.java index 5302a65df3c..89169919398 100644 --- a/core/src/main/java/bisq/core/offer/OpenOfferManager.java +++ b/core/src/main/java/bisq/core/offer/OpenOfferManager.java @@ -54,18 +54,14 @@ import bisq.common.handlers.ResultHandler; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.proto.persistable.PersistedDataHost; -import bisq.common.proto.persistable.PersistenceProtoResolver; import bisq.common.storage.Storage; import org.bitcoinj.core.Coin; import javax.inject.Inject; -import javax.inject.Named; import javafx.collections.ObservableList; -import java.io.File; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -127,10 +123,9 @@ public OpenOfferManager(KeyRing keyRing, ClosedTradableManager closedTradableManager, PriceFeedService priceFeedService, Preferences preferences, - PersistenceProtoResolver persistenceProtoResolver, TradeStatisticsManager tradeStatisticsManager, ArbitratorManager arbitratorManager, - @Named(Storage.STORAGE_DIR) File storageDir) { + Storage> storage) { this.keyRing = keyRing; this.user = user; this.p2PService = p2PService; @@ -144,7 +139,7 @@ public OpenOfferManager(KeyRing keyRing, this.tradeStatisticsManager = tradeStatisticsManager; this.arbitratorManager = arbitratorManager; - openOfferTradableListStorage = new Storage<>(storageDir, persistenceProtoResolver); + openOfferTradableListStorage = storage; // In case the app did get killed the shutDown from the modules is not called, so we use a shutdown hook Runtime.getRuntime().addShutdownHook(new Thread(() -> { diff --git a/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java b/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java index 96e7bc9775e..dbd7ebeef52 100644 --- a/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java +++ b/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java @@ -50,6 +50,7 @@ import bisq.common.proto.persistable.NavigationPath; import bisq.common.proto.persistable.PersistableEnvelope; import bisq.common.proto.persistable.PersistenceProtoResolver; +import bisq.common.storage.CorruptedDatabaseFilesHandler; import bisq.common.storage.Storage; import com.google.inject.Provider; @@ -69,15 +70,18 @@ public class CorePersistenceProtoResolver extends CoreProtoResolver implements P private final Provider btcWalletService; private final NetworkProtoResolver networkProtoResolver; private final File storageDir; + private final CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler; @Inject public CorePersistenceProtoResolver(Provider btcWalletService, NetworkProtoResolver networkProtoResolver, - @Named(Storage.STORAGE_DIR) File storageDir) { + @Named(Storage.STORAGE_DIR) File storageDir, + CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) { this.btcWalletService = btcWalletService; this.networkProtoResolver = networkProtoResolver; this.storageDir = storageDir; + this.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler; } @Override @@ -93,14 +97,14 @@ public PersistableEnvelope fromProto(protobuf.PersistableEnvelope proto) { case TRADABLE_LIST: return TradableList.fromProto(proto.getTradableList(), this, - new Storage<>(storageDir, this), + new Storage<>(storageDir, this, corruptedDatabaseFilesHandler), btcWalletService.get()); case TRADE_STATISTICS_LIST: throw new ProtobufferRuntimeException("TRADE_STATISTICS_LIST is not used anymore"); case DISPUTE_LIST: return DisputeList.fromProto(proto.getDisputeList(), this, - new Storage<>(storageDir, this)); + new Storage<>(storageDir, this, corruptedDatabaseFilesHandler)); case PREFERENCES_PAYLOAD: return PreferencesPayload.fromProto(proto.getPreferencesPayload(), this); case USER_PAYLOAD: diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 015a73ecff5..e603bb51b97 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -55,7 +55,6 @@ import bisq.common.handlers.ResultHandler; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.proto.persistable.PersistedDataHost; -import bisq.common.proto.persistable.PersistenceProtoResolver; import bisq.common.storage.Storage; import org.bitcoinj.core.AddressFormatException; @@ -64,7 +63,6 @@ import org.bitcoinj.core.Transaction; import javax.inject.Inject; -import javax.inject.Named; import com.google.common.util.concurrent.FutureCallback; @@ -78,8 +76,6 @@ import org.spongycastle.crypto.params.KeyParameter; -import java.io.File; - import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -148,11 +144,10 @@ public TradeManager(User user, FilterManager filterManager, TradeStatisticsManager tradeStatisticsManager, ReferralIdService referralIdService, - PersistenceProtoResolver persistenceProtoResolver, AccountAgeWitnessService accountAgeWitnessService, ArbitratorManager arbitratorManager, ClockWatcher clockWatcher, - @Named(Storage.STORAGE_DIR) File storageDir) { + Storage> storage) { this.user = user; this.keyRing = keyRing; this.btcWalletService = btcWalletService; @@ -170,7 +165,7 @@ public TradeManager(User user, this.arbitratorManager = arbitratorManager; this.clockWatcher = clockWatcher; - tradableListStorage = new Storage<>(storageDir, persistenceProtoResolver); + tradableListStorage = storage; p2PService.addDecryptedDirectMessageListener((decryptedMessageWithPubKey, peerNodeAddress) -> { NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); diff --git a/core/src/main/java/bisq/core/trade/closed/ClosedTradableManager.java b/core/src/main/java/bisq/core/trade/closed/ClosedTradableManager.java index d0569497227..ba96ac431c6 100644 --- a/core/src/main/java/bisq/core/trade/closed/ClosedTradableManager.java +++ b/core/src/main/java/bisq/core/trade/closed/ClosedTradableManager.java @@ -26,19 +26,14 @@ import bisq.common.crypto.KeyRing; import bisq.common.proto.persistable.PersistedDataHost; -import bisq.common.proto.persistable.PersistenceProtoResolver; import bisq.common.storage.Storage; import com.google.inject.Inject; -import javax.inject.Named; - import com.google.common.collect.ImmutableList; import javafx.collections.ObservableList; -import java.io.File; - import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -52,14 +47,14 @@ public class ClosedTradableManager implements PersistedDataHost { private final BtcWalletService btcWalletService; @Inject - public ClosedTradableManager(KeyRing keyRing, PriceFeedService priceFeedService, - PersistenceProtoResolver persistenceProtoResolver, + public ClosedTradableManager(KeyRing keyRing, + PriceFeedService priceFeedService, BtcWalletService btcWalletService, - @Named(Storage.STORAGE_DIR) File storageDir) { + Storage> storage) { this.keyRing = keyRing; this.priceFeedService = priceFeedService; this.btcWalletService = btcWalletService; - tradableListStorage = new Storage<>(storageDir, persistenceProtoResolver); + tradableListStorage = storage; // The ClosedTrades object can become a few MB so we don't keep so many backups tradableListStorage.setNumMaxBackupFiles(3); diff --git a/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java b/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java index 39b1342b449..b0c61e594a2 100644 --- a/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java +++ b/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java @@ -25,17 +25,12 @@ import bisq.common.crypto.KeyRing; import bisq.common.proto.persistable.PersistedDataHost; -import bisq.common.proto.persistable.PersistenceProtoResolver; import bisq.common.storage.Storage; import com.google.inject.Inject; -import javax.inject.Named; - import javafx.collections.ObservableList; -import java.io.File; - import java.util.Optional; import java.util.stream.Stream; @@ -51,14 +46,14 @@ public class FailedTradesManager implements PersistedDataHost { private final Storage> tradableListStorage; @Inject - public FailedTradesManager(KeyRing keyRing, PriceFeedService priceFeedService, - PersistenceProtoResolver persistenceProtoResolver, + public FailedTradesManager(KeyRing keyRing, + PriceFeedService priceFeedService, BtcWalletService btcWalletService, - @Named(Storage.STORAGE_DIR) File storageDir) { + Storage> storage) { this.keyRing = keyRing; this.priceFeedService = priceFeedService; this.btcWalletService = btcWalletService; - tradableListStorage = new Storage<>(storageDir, persistenceProtoResolver); + tradableListStorage = storage; } diff --git a/core/src/test/java/bisq/core/offer/OpenOfferManagerTest.java b/core/src/test/java/bisq/core/offer/OpenOfferManagerTest.java index 41df4299fbb..ba7187977a8 100644 --- a/core/src/test/java/bisq/core/offer/OpenOfferManagerTest.java +++ b/core/src/test/java/bisq/core/offer/OpenOfferManagerTest.java @@ -1,14 +1,18 @@ package bisq.core.offer; +import bisq.core.trade.TradableList; + import bisq.network.p2p.P2PService; import bisq.network.p2p.peers.PeerManager; import bisq.common.handlers.ErrorMessageHandler; import bisq.common.handlers.ResultHandler; +import bisq.common.storage.CorruptedDatabaseFilesHandler; import bisq.common.storage.Storage; import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.Before; import org.junit.Test; import static bisq.core.offer.OfferMaker.btcUsdOffer; @@ -19,6 +23,13 @@ public class OpenOfferManagerTest { + private CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler; + + @Before + public void setUp() throws Exception { + corruptedDatabaseFilesHandler = mock(CorruptedDatabaseFilesHandler.class); + } + @Test public void testStartEditOfferForActiveOffer() { P2PService p2PService = mock(P2PService.class); @@ -28,8 +39,8 @@ public void testStartEditOfferForActiveOffer() { final OpenOfferManager manager = new OpenOfferManager(null, null, p2PService, null, null, null, offerBookService, - null, null, null, null, - null, null, null); + null, null, null, + null, null, new Storage>(null, null, corruptedDatabaseFilesHandler)); AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false); @@ -63,8 +74,8 @@ public void testStartEditOfferForDeactivatedOffer() { final OpenOfferManager manager = new OpenOfferManager(null, null, p2PService, null, null, null, offerBookService, - null, null, null, null, - null, null, null); + null, null, null, + null, null, new Storage>(null, null, corruptedDatabaseFilesHandler)); AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false); @@ -90,8 +101,8 @@ public void testStartEditOfferForOfferThatIsCurrentlyEdited() { final OpenOfferManager manager = new OpenOfferManager(null, null, p2PService, null, null, null, offerBookService, - null, null, null, null, - null, null, null); + null, null, null, + null, null, new Storage>(null, null, corruptedDatabaseFilesHandler)); AtomicBoolean startEditOfferSuccessful = new AtomicBoolean(false); diff --git a/core/src/test/java/bisq/core/trade/TradableListTest.java b/core/src/test/java/bisq/core/trade/TradableListTest.java index 2b0d1012b31..64eff93f2cf 100644 --- a/core/src/test/java/bisq/core/trade/TradableListTest.java +++ b/core/src/test/java/bisq/core/trade/TradableListTest.java @@ -21,6 +21,7 @@ import bisq.core.offer.OfferPayload; import bisq.core.offer.OpenOffer; +import bisq.common.storage.CorruptedDatabaseFilesHandler; import bisq.common.storage.Storage; import org.junit.Test; @@ -36,7 +37,7 @@ public class TradableListTest { @Test public void protoTesting() { OfferPayload offerPayload = mock(OfferPayload.class, RETURNS_DEEP_STUBS); - Storage> storage = new Storage<>(null, null); + Storage> storage = new Storage<>(null, null, mock(CorruptedDatabaseFilesHandler.class)); TradableList openOfferTradableList = new TradableList<>(storage, "filename"); protobuf.PersistableEnvelope message = (protobuf.PersistableEnvelope) openOfferTradableList.toProtoMessage(); assertTrue(message.getMessageCase().equals(TRADABLE_LIST)); diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsDataModel.java b/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsDataModel.java index b37aa50d3ad..25b8906b990 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsDataModel.java @@ -32,6 +32,7 @@ import bisq.core.user.User; import bisq.common.proto.persistable.PersistenceProtoResolver; +import bisq.common.storage.CorruptedDatabaseFilesHandler; import com.google.inject.Inject; @@ -56,6 +57,7 @@ class AltCoinAccountsDataModel extends ActivatableDataModel { private final SetChangeListener setChangeListener; private final String accountsFileName = "AltcoinPaymentAccounts"; private final PersistenceProtoResolver persistenceProtoResolver; + private final CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler; @Inject public AltCoinAccountsDataModel(User user, @@ -63,13 +65,15 @@ public AltCoinAccountsDataModel(User user, OpenOfferManager openOfferManager, TradeManager tradeManager, AccountAgeWitnessService accountAgeWitnessService, - PersistenceProtoResolver persistenceProtoResolver) { + PersistenceProtoResolver persistenceProtoResolver, + CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) { this.user = user; this.preferences = preferences; this.openOfferManager = openOfferManager; this.tradeManager = tradeManager; this.accountAgeWitnessService = accountAgeWitnessService; this.persistenceProtoResolver = persistenceProtoResolver; + this.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler; setChangeListener = change -> fillAndSortPaymentAccounts(); } @@ -144,11 +148,11 @@ public void exportAccounts(Stage stage) { ArrayList accounts = new ArrayList<>(user.getPaymentAccounts().stream() .filter(paymentAccount -> paymentAccount instanceof AssetAccount) .collect(Collectors.toList())); - GUIUtil.exportAccounts(accounts, accountsFileName, preferences, stage, persistenceProtoResolver); + GUIUtil.exportAccounts(accounts, accountsFileName, preferences, stage, persistenceProtoResolver, corruptedDatabaseFilesHandler); } } public void importAccounts(Stage stage) { - GUIUtil.importAccounts(user, accountsFileName, preferences, stage, persistenceProtoResolver); + GUIUtil.importAccounts(user, accountsFileName, preferences, stage, persistenceProtoResolver, corruptedDatabaseFilesHandler); } } diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java index 331fbf237c4..568b3d8c21e 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java @@ -33,6 +33,7 @@ import bisq.core.user.User; import bisq.common.proto.persistable.PersistenceProtoResolver; +import bisq.common.storage.CorruptedDatabaseFilesHandler; import com.google.inject.Inject; @@ -58,6 +59,7 @@ class FiatAccountsDataModel extends ActivatableDataModel { private final SetChangeListener setChangeListener; private final String accountsFileName = "FiatPaymentAccounts"; private final PersistenceProtoResolver persistenceProtoResolver; + private final CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler; @Inject public FiatAccountsDataModel(User user, @@ -65,13 +67,15 @@ public FiatAccountsDataModel(User user, OpenOfferManager openOfferManager, TradeManager tradeManager, AccountAgeWitnessService accountAgeWitnessService, - PersistenceProtoResolver persistenceProtoResolver) { + PersistenceProtoResolver persistenceProtoResolver, + CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) { this.user = user; this.preferences = preferences; this.openOfferManager = openOfferManager; this.tradeManager = tradeManager; this.accountAgeWitnessService = accountAgeWitnessService; this.persistenceProtoResolver = persistenceProtoResolver; + this.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler; setChangeListener = change -> fillAndSortPaymentAccounts(); } @@ -147,11 +151,11 @@ public void exportAccounts(Stage stage) { ArrayList accounts = new ArrayList<>(user.getPaymentAccounts().stream() .filter(paymentAccount -> !(paymentAccount instanceof AssetAccount)) .collect(Collectors.toList())); - GUIUtil.exportAccounts(accounts, accountsFileName, preferences, stage, persistenceProtoResolver); + GUIUtil.exportAccounts(accounts, accountsFileName, preferences, stage, persistenceProtoResolver, corruptedDatabaseFilesHandler); } } public void importAccounts(Stage stage) { - GUIUtil.importAccounts(user, accountsFileName, preferences, stage, persistenceProtoResolver); + GUIUtil.importAccounts(user, accountsFileName, preferences, stage, persistenceProtoResolver, corruptedDatabaseFilesHandler); } } diff --git a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java index 36d9cee3f6f..aa772f2c531 100644 --- a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java +++ b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java @@ -48,6 +48,7 @@ import bisq.common.app.DevEnv; import bisq.common.proto.persistable.PersistableList; import bisq.common.proto.persistable.PersistenceProtoResolver; +import bisq.common.storage.CorruptedDatabaseFilesHandler; import bisq.common.storage.FileUtil; import bisq.common.storage.Storage; import bisq.common.util.Tuple2; @@ -189,11 +190,11 @@ public static void showFeeInfoBeforeExecute(Runnable runnable) { } public static void exportAccounts(ArrayList accounts, String fileName, - Preferences preferences, Stage stage, PersistenceProtoResolver persistenceProtoResolver) { + Preferences preferences, Stage stage, PersistenceProtoResolver persistenceProtoResolver, CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) { if (!accounts.isEmpty()) { String directory = getDirectoryFromChooser(preferences, stage); if (directory != null && !directory.isEmpty()) { - Storage> paymentAccountsStorage = new Storage<>(new File(directory), persistenceProtoResolver); + Storage> paymentAccountsStorage = new Storage<>(new File(directory), persistenceProtoResolver, corruptedDatabaseFilesHandler); paymentAccountsStorage.initAndGetPersisted(new PaymentAccountList(accounts), fileName, 100); paymentAccountsStorage.queueUpForSave(); new Popup<>().feedback(Res.get("guiUtil.accountExport.savedToPath", Paths.get(directory, fileName).toAbsolutePath())).show(); @@ -204,7 +205,7 @@ public static void exportAccounts(ArrayList accounts, String fil } public static void importAccounts(User user, String fileName, Preferences preferences, Stage stage, - PersistenceProtoResolver persistenceProtoResolver) { + PersistenceProtoResolver persistenceProtoResolver, CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) { FileChooser fileChooser = new FileChooser(); File initDir = new File(preferences.getDirectoryChooserPath()); if (initDir.isDirectory()) { @@ -217,7 +218,7 @@ public static void importAccounts(User user, String fileName, Preferences prefer if (Paths.get(path).getFileName().toString().equals(fileName)) { String directory = Paths.get(path).getParent().toString(); preferences.setDirectoryChooserPath(directory); - Storage paymentAccountsStorage = new Storage<>(new File(directory), persistenceProtoResolver); + Storage paymentAccountsStorage = new Storage<>(new File(directory), persistenceProtoResolver, corruptedDatabaseFilesHandler); PaymentAccountList persisted = paymentAccountsStorage.initAndGetPersistedWithFileName(fileName, 100); if (persisted != null) { final StringBuilder msg = new StringBuilder(); diff --git a/desktop/src/test/java/bisq/desktop/GuiceSetupTest.java b/desktop/src/test/java/bisq/desktop/GuiceSetupTest.java index ef55e99c39f..32a6298d9bb 100644 --- a/desktop/src/test/java/bisq/desktop/GuiceSetupTest.java +++ b/desktop/src/test/java/bisq/desktop/GuiceSetupTest.java @@ -50,6 +50,7 @@ import bisq.common.proto.network.NetworkProtoResolver; import bisq.common.proto.persistable.PersistenceProtoResolver; import bisq.common.storage.CorruptedDatabaseFilesHandler; +import bisq.common.storage.Storage; import org.springframework.mock.env.MockPropertySource; @@ -59,6 +60,7 @@ import org.junit.Before; import org.junit.Test; +import static junit.framework.TestCase.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; @@ -129,9 +131,15 @@ public void testGuiceSetup() { assertSingleton(TradeEvents.class); assertSingleton(PriceAlert.class); assertSingleton(MarketAlerts.class); + + assertNotSingleton(Storage.class); } private void assertSingleton(Class type) { assertSame(injector.getInstance(type), injector.getInstance(type)); } + + private void assertNotSingleton(Class type) { + assertNotSame(injector.getInstance(type), injector.getInstance(type)); + } } diff --git a/monitor/src/main/java/bisq/monitor/metric/P2PNetworkLoad.java b/monitor/src/main/java/bisq/monitor/metric/P2PNetworkLoad.java index a5a0c27e604..a62bd78c468 100644 --- a/monitor/src/main/java/bisq/monitor/metric/P2PNetworkLoad.java +++ b/monitor/src/main/java/bisq/monitor/metric/P2PNetworkLoad.java @@ -38,6 +38,7 @@ import bisq.network.p2p.peers.PeerManager; import bisq.network.p2p.peers.keepalive.KeepAliveManager; import bisq.network.p2p.peers.peerexchange.PeerExchangeManager; +import bisq.network.p2p.peers.peerexchange.PeerList; import bisq.network.p2p.storage.messages.BroadcastMessage; import bisq.common.ClockWatcher; @@ -45,6 +46,8 @@ import bisq.common.app.Capability; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.proto.network.NetworkProtoResolver; +import bisq.common.storage.CorruptedDatabaseFilesHandler; +import bisq.common.storage.Storage; import org.springframework.core.env.PropertySource; @@ -136,13 +139,14 @@ public String getProperty(String name) { return ""; } }); + CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler = new CorruptedDatabaseFilesHandler(); int maxConnections = Integer.parseInt(configuration.getProperty(MAX_CONNECTIONS, "12")); NetworkProtoResolver networkProtoResolver = new CoreNetworkProtoResolver(); CorePersistenceProtoResolver persistenceProtoResolver = new CorePersistenceProtoResolver(null, - networkProtoResolver, storageDir); + networkProtoResolver, storageDir, corruptedDatabaseFilesHandler); DefaultSeedNodeRepository seedNodeRepository = new DefaultSeedNodeRepository(environment, null); PeerManager peerManager = new PeerManager(networkNode, seedNodeRepository, new ClockWatcher(), - persistenceProtoResolver, maxConnections, storageDir); + maxConnections, new Storage(storageDir, persistenceProtoResolver, corruptedDatabaseFilesHandler)); // init file storage peerManager.readPersisted(); diff --git a/p2p/src/main/java/bisq/network/p2p/peers/PeerManager.java b/p2p/src/main/java/bisq/network/p2p/peers/PeerManager.java index 9837b86b5a4..dbea7462c99 100644 --- a/p2p/src/main/java/bisq/network/p2p/peers/PeerManager.java +++ b/p2p/src/main/java/bisq/network/p2p/peers/PeerManager.java @@ -34,15 +34,12 @@ import bisq.common.UserThread; import bisq.common.app.Capabilities; import bisq.common.proto.persistable.PersistedDataHost; -import bisq.common.proto.persistable.PersistenceProtoResolver; import bisq.common.storage.Storage; import com.google.inject.name.Named; import javax.inject.Inject; -import java.io.File; - import java.util.ArrayList; import java.util.Comparator; import java.util.Date; @@ -84,7 +81,6 @@ public class PeerManager implements ConnectionListener, PersistedDataHost { private Set latestLivePeers = new HashSet<>(); - /////////////////////////////////////////////////////////////////////////////////////////// // Listener /////////////////////////////////////////////////////////////////////////////////////////// @@ -133,13 +129,12 @@ public interface Listener { public PeerManager(NetworkNode networkNode, SeedNodeRepository seedNodeRepository, ClockWatcher clockWatcher, - PersistenceProtoResolver persistenceProtoResolver, @Named(NetworkOptionKeys.MAX_CONNECTIONS) int maxConnections, - @Named(Storage.STORAGE_DIR) File storageDir) { + Storage storage) { this.networkNode = networkNode; this.seedNodeAddresses = new HashSet<>(seedNodeRepository.getSeedNodeAddresses()); this.clockWatcher = clockWatcher; - storage = new Storage<>(storageDir, persistenceProtoResolver); + this.storage = storage; this.networkNode.addConnectionListener(this); diff --git a/p2p/src/test/java/bisq/network/p2p/TestUtils.java b/p2p/src/test/java/bisq/network/p2p/TestUtils.java index ba3e2930c71..b483fde4b3c 100644 --- a/p2p/src/test/java/bisq/network/p2p/TestUtils.java +++ b/p2p/src/test/java/bisq/network/p2p/TestUtils.java @@ -22,7 +22,6 @@ import bisq.common.proto.network.NetworkPayload; import bisq.common.proto.network.NetworkProtoResolver; import bisq.common.proto.persistable.PersistableEnvelope; -import bisq.common.proto.persistable.PersistenceProtoResolver; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -187,23 +186,4 @@ public NetworkPayload fromProto(protobuf.StorageEntryWrapper proto) { } }; } - - public static PersistenceProtoResolver getPersistenceProtoResolver() { - return new PersistenceProtoResolver() { - @Override - public Payload fromProto(protobuf.PaymentAccountPayload proto) { - return null; - } - - @Override - public PersistableEnvelope fromProto(protobuf.PersistableEnvelope persistable) { - return null; - } - - @Override - public PersistableEnvelope fromProto(protobuf.PersistableNetworkPayload persistable) { - return null; - } - }; - } } diff --git a/p2p/src/test/java/bisq/network/p2p/storage/P2PDataStorageTest.java b/p2p/src/test/java/bisq/network/p2p/storage/P2PDataStorageTest.java index 8af80e2a1b8..a26e8e021de 100644 --- a/p2p/src/test/java/bisq/network/p2p/storage/P2PDataStorageTest.java +++ b/p2p/src/test/java/bisq/network/p2p/storage/P2PDataStorageTest.java @@ -1,221 +1,28 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - package bisq.network.p2p.storage; -import bisq.network.crypto.EncryptionService; -import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.TestUtils; import bisq.network.p2p.network.NetworkNode; import bisq.network.p2p.peers.Broadcaster; -import bisq.network.p2p.storage.payload.ProtectedStoragePayload; - -import bisq.common.crypto.CryptoException; -import bisq.common.crypto.KeyRing; -import bisq.common.crypto.KeyStorage; -import bisq.common.proto.network.NetworkProtoResolver; -import bisq.common.proto.persistable.PersistenceProtoResolver; -import bisq.common.storage.FileUtil; - -import java.security.InvalidKeyException; -import java.security.KeyPair; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; -import java.security.cert.CertificateException; - -import java.nio.file.Path; -import java.nio.file.Paths; +import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService; +import bisq.network.p2p.storage.persistence.ProtectedDataStoreService; +import bisq.network.p2p.storage.persistence.ResourceDataStoreService; -import java.io.File; -import java.io.IOException; +import bisq.common.storage.Storage; -import java.util.HashSet; -import java.util.Set; +import java.time.Clock; -import org.junit.After; -import org.junit.Before; +import org.junit.Test; import static org.mockito.Mockito.mock; public class P2PDataStorageTest { - private final Set seedNodes = new HashSet<>(); - private EncryptionService encryptionService1, encryptionService2; - private P2PDataStorage dataStorage1; - private KeyPair storageSignatureKeyPair1, storageSignatureKeyPair2; - private KeyRing keyRing1, keyRing2; - private ProtectedStoragePayload protectedStoragePayload; - private File dir1; - private File dir2; - - Broadcaster broadcaster = mock(Broadcaster.class); - NetworkNode networkNode = mock(NetworkNode.class); - NetworkProtoResolver networkProtoResolver = mock(NetworkProtoResolver.class); - PersistenceProtoResolver persistenceProtoResolver = mock(PersistenceProtoResolver.class); - - @Before - public void setup() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException { - - dir1 = File.createTempFile("temp_tests1", ""); - //noinspection ResultOfMethodCallIgnored - dir1.delete(); - //noinspection ResultOfMethodCallIgnored - dir1.mkdir(); - dir2 = File.createTempFile("temp_tests2", ""); - //noinspection ResultOfMethodCallIgnored - dir2.delete(); - //noinspection ResultOfMethodCallIgnored - dir2.mkdir(); - - keyRing1 = new KeyRing(new KeyStorage(dir1)); - storageSignatureKeyPair1 = keyRing1.getSignatureKeyPair(); - encryptionService1 = new EncryptionService(keyRing1, TestUtils.getNetworkProtoResolver()); - - // for mailbox - keyRing2 = new KeyRing(new KeyStorage(dir2)); - storageSignatureKeyPair2 = keyRing2.getSignatureKeyPair(); - encryptionService2 = new EncryptionService(keyRing2, TestUtils.getNetworkProtoResolver()); - //dataStorage1 = new P2PDataStorage(broadcaster, networkNode, dir1, persistenceProtoResolver); - } - - @After - public void tearDown() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException { - Path path = Paths.get(TestUtils.test_dummy_dir); - File dir = path.toFile(); - FileUtil.deleteDirectory(dir); - FileUtil.deleteDirectory(dir1); - FileUtil.deleteDirectory(dir2); - } - - /* @Test - public void testProtectedStorageEntryAddAndRemove() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException, NoSuchProviderException { - storagePayload = new AlertPayload(new AlertVO("alert", - false, - "version", - storageSignatureKeyPair1.getPublic().getEncoded(), - "sig", - null)); - - ProtectedStorageEntry data = dataStorage1.getProtectedData(storagePayload, storageSignatureKeyPair1); - assertTrue(dataStorage1.add(data, null, null, true)); - assertEquals(1, dataStorage1.getMap().size()); - - int newSequenceNumber = data.sequenceNumber + 1; - byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.getStoragePayload(), newSequenceNumber)); - byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); - ProtectedStorageEntry dataToRemove = new ProtectedStorageEntry(data.getStoragePayload(), data.ownerPubKey, newSequenceNumber, signature); - assertTrue(dataStorage1.remove(dataToRemove, null, true)); - assertEquals(0, dataStorage1.getMap().size()); - } - @Test - public void testProtectedStorageEntryRoundtrip() throws InterruptedException, NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, CryptoException, SignatureException, InvalidKeyException, NoSuchProviderException { - //mockData = new MockData("mockData", keyRing1.getSignatureKeyPair().getPublic()); - storagePayload = getDummyOffer(); - - ProtectedStorageEntry data = dataStorage1.getProtectedData(storagePayload, storageSignatureKeyPair1); - setSignature(data); - assertTrue(checkSignature(data)); - - ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); - data.toEnvelopeProto().writeTo(byteOutputStream); - - //TODO Use NetworkProtoResolver, PersistenceProtoResolver or ProtoResolver which are all in io.bisq.common. - ProtectedStorageEntry protectedStorageEntry = ProtoBufferUtilities.getProtectedStorageEntry(PB.ProtectedStorageEntry.parseFrom(new ByteArrayInputStream(byteOutputStream.toByteArray()))); - - assertTrue(Arrays.equals(Hash.getHash(data.getStoragePayload()), Hash.getHash(protectedStorageEntry.getStoragePayload()))); - assertTrue(data.equals(protectedStorageEntry)); - assertTrue(checkSignature(protectedStorageEntry)); - }*/ - - //TODO Use NetworkProtoResolver, PersistenceProtoResolver or ProtoResolver which are all in io.bisq.common. - /* @Test - public void testOfferRoundtrip() throws InvalidProtocolBufferException { - OfferPayload offer = getDummyOffer(); - try { - String buffer = JsonFormat.printer().print(offer.toEnvelopeProto().getOfferPayload()); - JsonFormat.Parser parser = JsonFormat.parser(); - PB.OfferPayload.Builder builder = PB.OfferPayload.newBuilder(); - parser.merge(buffer, builder); - assertEquals(offer, ProtoBufferUtilities.getOfferPayload(builder.build())); - } catch (IOException e) { - e.printStackTrace(); - fail(); - } - }*/ - - /* @NotNull - private OfferPayload getDummyOffer() { - NodeAddress nodeAddress = new NodeAddress("host", 1000); - NodeAddress nodeAddress2 = new NodeAddress("host1", 1001); - NodeAddress nodeAddress3 = new NodeAddress("host2", 1002); - NodeAddress nodeAddress4 = new NodeAddress("host3", 1002); - return new OfferPayload("id", - System.currentTimeMillis(), - nodeAddress4, - keyRing1.getPubKeyRing(), - OfferPayload.Direction.BUY, - 1200, - 1.5, - true, - 100, - 50, - "BTC", - "USD", - Lists.newArrayList(nodeAddress, - nodeAddress2, - nodeAddress3), - Lists.newArrayList(nodeAddress, - nodeAddress2, - nodeAddress3), - "SEPA", - "accountid", - "feetxId", - "BE", - Lists.newArrayList("BE", "AU"), - "bankid", - Lists.newArrayList("BANK1", "BANK2"), - "version", - 100, - 100, - 100, - 100, - 1000, - 1000, - 1000, - false, - false, - - 1000, - 1000, - false, - "hash", - null); - } + public void canStart1Instance() { + P2PDataStorage storage = new P2PDataStorage(mock(NetworkNode.class), + mock(Broadcaster.class), + mock(AppendOnlyDataStoreService.class), + mock(ProtectedDataStoreService.class), mock(ResourceDataStoreService.class), + mock(Storage.class), Clock.systemUTC()); - private void setSignature(ProtectedStorageEntry entry) throws CryptoException { - int newSequenceNumber = entry.sequenceNumber; - byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(entry.getStoragePayload(), newSequenceNumber)); - byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); - entry.signature = signature; } - private boolean checkSignature(ProtectedStorageEntry entry) throws CryptoException { - byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(entry.getStoragePayload(), entry.sequenceNumber)); - return dataStorage1.checkSignature(entry.ownerPubKey, hashOfDataAndSeqNr, entry.signature); - }*/ }