Require password at startup, heck for open offers at emptying wallet, add check for isBootstrapped,

This commit is contained in:
Manfred Karrer 2016-04-07 02:54:52 +02:00
parent 5af70848a7
commit 0ebf3f6b36
12 changed files with 74 additions and 74 deletions

View File

@ -145,8 +145,12 @@ public class ArbitratorManager {
ArbitratorManager.this.onBootstrapComplete();
}
};
p2PService.addP2PServiceListener(bootstrapListener);
if (p2PService.isBootstrapped())
onBootstrapComplete();
else
p2PService.addP2PServiceListener(bootstrapListener);
} else {
republishArbitrator();
}

View File

@ -125,7 +125,10 @@ public class DisputeManager {
applyMessages();
}
};
p2PService.addP2PServiceListener(bootstrapListener);
if (p2PService.isBootstrapped())
applyMessages();
else
p2PService.addP2PServiceListener(bootstrapListener);
}
private void applyMessages() {
@ -146,7 +149,8 @@ public class DisputeManager {
});
decryptedMailboxMessageWithPubKeys.clear();
p2PService.removeP2PServiceListener(bootstrapListener);
if (bootstrapListener != null)
p2PService.removeP2PServiceListener(bootstrapListener);
}

View File

@ -151,13 +151,15 @@ public class TradeManager {
bootstrapListener = new BootstrapListener() {
@Override
public void onBootstrapComplete() {
Log.traceCall("onNetworkReady");
// Get called after onMailboxMessageAdded from initial data request
// The mailbox message will be removed inside the tasks after they are processed successfully
initPendingTrades();
}
};
p2PService.addP2PServiceListener(bootstrapListener);
if (p2PService.isBootstrapped())
initPendingTrades();
else
p2PService.addP2PServiceListener(bootstrapListener);
}
@ -167,7 +169,8 @@ public class TradeManager {
private void initPendingTrades() {
Log.traceCall();
p2PService.removeP2PServiceListener(bootstrapListener);
if (bootstrapListener != null)
p2PService.removeP2PServiceListener(bootstrapListener);
//List<Trade> failedTrades = new ArrayList<>();
for (Trade trade : trades) {

View File

@ -53,6 +53,7 @@ import javax.annotation.Nullable;
import javax.inject.Named;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@ -121,6 +122,11 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
};
p2PService.addP2PServiceListener(bootstrapListener);
p2PService.addDecryptedDirectMessageListener(this);
if (p2PService.isBootstrapped())
onBootstrapComplete();
else
p2PService.addP2PServiceListener(bootstrapListener);
}
@SuppressWarnings("WeakerAccess")
@ -151,6 +157,15 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
UserThread.runAfter(completeHandler::run, openOffers.size() * 100 + 200, TimeUnit.MILLISECONDS);
}
public void removeAllOpenOffers(@Nullable Runnable completeHandler) {
List<OpenOffer> openOffersList = new ArrayList<>(openOffers);
openOffersList.forEach(openOffer -> removeOpenOffer(openOffer, () -> {
}, errorMessage -> {
}));
if (completeHandler != null)
UserThread.runAfter(completeHandler::run, openOffers.size() * 100 + 200, TimeUnit.MILLISECONDS);
}
///////////////////////////////////////////////////////////////////////////////////////////
// DecryptedDirectMessageListener implementation
///////////////////////////////////////////////////////////////////////////////////////////
@ -172,7 +187,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
///////////////////////////////////////////////////////////////////////////////////////////
public void onBootstrapComplete() {
p2PService.removeP2PServiceListener(bootstrapListener);
if (bootstrapListener != null)
p2PService.removeP2PServiceListener(bootstrapListener);
stopped = false;

View File

@ -409,13 +409,10 @@ public class MainViewModel implements ViewModel {
}
private void onAllServicesInitialized() {
// We need to request the password in case we have an encrypted wallet as we need to set the aesKey to our trading wallet.
// In case we have any offers open or a pending trade we need to unlock our trading wallet so a trade can be executed automatically
// Otherwise we delay the password request to create offer, or take offer.
// When the password is set it will be stored to the tradeWalletService as well, so its only needed after a restart.
if (walletService.getWallet().isEncrypted() &&
(openOfferManager.getOpenOffers().size() > 0
|| tradeManager.getTrades().size() > 0
|| disputeManager.getDisputesAsObservableList().size() > 0)) {
if (walletService.getWallet().isEncrypted()) {
walletPasswordWindow
.onAesKey(aesKey -> {
tradeWalletService.setAesKey(aesKey);

View File

@ -145,9 +145,7 @@ public class PasswordView extends ActivatableView<GridPane, Void> {
addMultilineLabel(root, gridRow,
"With password protection you need to enter your password when" +
" withdrawing bitcoin out of your wallet or " +
"if you want to view or restore a wallet from seed words.\n" +
"For the transactions used in the trade process we don't support password protection as that would make automatic offer " +
"execution impossible, but you need to provide the password at application startup if you have open offer, trades or disputes.",
"if you want to view or restore a wallet from seed words as well as at application startup.",
Layout.FIRST_ROW_AND_GROUP_DISTANCE);
}

View File

@ -37,7 +37,6 @@ import io.bitsquare.gui.main.overlays.windows.DisputeSummaryWindow;
import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.GUIUtil;
import io.bitsquare.p2p.BootstrapListener;
import io.bitsquare.p2p.P2PService;
import io.bitsquare.p2p.network.Connection;
import io.bitsquare.trade.Trade;
@ -110,7 +109,6 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
private TableGroupHeadline tableGroupHeadline;
private ObservableList<DisputeCommunicationMessage> disputeCommunicationMessages;
private Button sendButton;
private boolean isBootstrapped;
private Subscription inputTextAreaTextSubscription;
@ -175,17 +173,6 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
};
disputeDirectMessageListListener = c -> scrollToBottom();
if (!p2PService.isBootstrapped()) {
p2PService.addP2PServiceListener(new BootstrapListener() {
@Override
public void onBootstrapComplete() {
isBootstrapped = true;
}
});
} else {
isBootstrapped = true;
}
}
@Override
@ -425,7 +412,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
sendButton = new Button("Send");
sendButton.setDefaultButton(true);
sendButton.setOnAction(e -> {
if (isBootstrapped) {
if (p2PService.isBootstrapped()) {
String text = inputTextArea.getText();
if (!text.isEmpty())
onSendMessage(text, selectedDispute);

View File

@ -25,6 +25,7 @@ import io.bitsquare.btc.AddressEntryException;
import io.bitsquare.btc.Restrictions;
import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.gui.common.view.ActivatableView;
import io.bitsquare.gui.common.view.FxmlView;
@ -58,6 +59,7 @@ import org.spongycastle.crypto.params.KeyParameter;
import javax.inject.Inject;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@FxmlView
@ -281,7 +283,9 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
private void doWithdraw(Coin amount, FutureCallback<Transaction> callback) {
if (walletService.getWallet().isEncrypted()) {
walletPasswordWindow.onAesKey(aesKey -> sendFunds(amount, aesKey, callback)).show();
UserThread.runAfter(() -> walletPasswordWindow.onAesKey(aesKey ->
sendFunds(amount, aesKey, callback))
.show(), 300, TimeUnit.MILLISECONDS);
} else {
sendFunds(amount, null, callback);
}

View File

@ -30,7 +30,6 @@ import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.model.ActivatableDataModel;
import io.bitsquare.gui.main.overlays.notifications.Notification;
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.p2p.P2PService;
@ -63,14 +62,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
class CreateOfferDataModel extends ActivatableDataModel {
private final OpenOfferManager openOfferManager;
final WalletService walletService;
private final TradeWalletService tradeWalletService;
final TradeWalletService tradeWalletService;
private final Preferences preferences;
private final User user;
private final KeyRing keyRing;
private final P2PService p2PService;
private final PriceFeed priceFeed;
private Navigation navigation;
private final WalletPasswordWindow walletPasswordWindow;
private final BlockchainService blockchainService;
private final BSFormatter formatter;
private final String offerId;
@ -117,8 +115,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
@Inject
CreateOfferDataModel(OpenOfferManager openOfferManager, WalletService walletService, TradeWalletService tradeWalletService,
Preferences preferences, User user, KeyRing keyRing, P2PService p2PService, PriceFeed priceFeed,
Navigation navigation,
WalletPasswordWindow walletPasswordWindow, BlockchainService blockchainService, BSFormatter formatter) {
Navigation navigation, BlockchainService blockchainService, BSFormatter formatter) {
this.openOfferManager = openOfferManager;
this.walletService = walletService;
this.tradeWalletService = tradeWalletService;
@ -128,7 +125,6 @@ class CreateOfferDataModel extends ActivatableDataModel {
this.p2PService = p2PService;
this.priceFeed = priceFeed;
this.navigation = navigation;
this.walletPasswordWindow = walletPasswordWindow;
this.blockchainService = blockchainService;
this.formatter = formatter;
@ -286,17 +282,6 @@ class CreateOfferDataModel extends ActivatableDataModel {
}
void onPlaceOffer(Offer offer, TransactionResultHandler resultHandler) {
if (walletService.getWallet().isEncrypted() && tradeWalletService.getAesKey() == null) {
walletPasswordWindow.onAesKey(aesKey -> {
tradeWalletService.setAesKey(aesKey);
doPlaceOffer(offer, resultHandler);
}).show();
} else {
doPlaceOffer(offer, resultHandler);
}
}
private void doPlaceOffer(Offer offer, TransactionResultHandler resultHandler) {
openOfferManager.placeOffer(offer, totalToPayAsCoin.get().subtract(offerFeeAsCoin), useSavingsWallet, resultHandler);
}

View File

@ -29,7 +29,6 @@ import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.btc.pricefeed.PriceFeed;
import io.bitsquare.gui.common.model.ActivatableDataModel;
import io.bitsquare.gui.main.overlays.notifications.Notification;
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.locale.TradeCurrency;
@ -61,10 +60,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
class TakeOfferDataModel extends ActivatableDataModel {
private final TradeManager tradeManager;
private final TradeWalletService tradeWalletService;
private final WalletService walletService;
final TradeWalletService tradeWalletService;
final WalletService walletService;
private final User user;
private final WalletPasswordWindow walletPasswordWindow;
private final Preferences preferences;
private final PriceFeed priceFeed;
private final BlockchainService blockchainService;
@ -103,14 +101,13 @@ class TakeOfferDataModel extends ActivatableDataModel {
@Inject
TakeOfferDataModel(TradeManager tradeManager, TradeWalletService tradeWalletService,
WalletService walletService, User user, WalletPasswordWindow walletPasswordWindow,
WalletService walletService, User user,
Preferences preferences, PriceFeed priceFeed, BlockchainService blockchainService,
BSFormatter formatter) {
this.tradeManager = tradeManager;
this.tradeWalletService = tradeWalletService;
this.walletService = walletService;
this.user = user;
this.walletPasswordWindow = walletPasswordWindow;
this.preferences = preferences;
this.priceFeed = priceFeed;
this.blockchainService = blockchainService;
@ -227,17 +224,6 @@ class TakeOfferDataModel extends ActivatableDataModel {
// errorMessageHandler is used only in the check availability phase. As soon we have a trade we write the error msg in the trade object as we want to
// have it persisted as well.
void onTakeOffer(TradeResultHandler tradeResultHandler) {
if (walletService.getWallet().isEncrypted() && tradeWalletService.getAesKey() == null) {
walletPasswordWindow.onAesKey(aesKey -> {
tradeWalletService.setAesKey(aesKey);
doTakeOffer(tradeResultHandler);
}).show();
} else {
doTakeOffer(tradeResultHandler);
}
}
private void doTakeOffer(TradeResultHandler tradeResultHandler) {
tradeManager.onTakeOffer(amountAsCoin.get(),
totalToPayAsCoin.get().subtract(takerFeeAsCoin),
offer,

View File

@ -62,7 +62,8 @@ public class EmptyWalletWindow extends Overlay<EmptyWalletWindow> {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public EmptyWalletWindow(WalletService walletService, WalletPasswordWindow walletPasswordWindow, OpenOfferManager openOfferManager, BSFormatter formatter) {
public EmptyWalletWindow(WalletService walletService, WalletPasswordWindow walletPasswordWindow,
OpenOfferManager openOfferManager, BSFormatter formatter) {
this.walletService = walletService;
this.walletPasswordWindow = walletPasswordWindow;
this.openOfferManager = openOfferManager;
@ -140,8 +141,23 @@ public class EmptyWalletWindow extends Overlay<EmptyWalletWindow> {
}
private void doEmptyWallet(KeyParameter aesKey) {
if (!openOfferManager.getOpenOffers().isEmpty()) {
UserThread.runAfter(() ->
new Popup().warning("You have open offers which will be removed if you empty the wallet.\n" +
"Are you sure that you want to empty your wallet?")
.actionButtonText("Yes, I am sure")
.onAction(() -> {
doEmptyWallet2(aesKey);
})
.show(), 300, TimeUnit.MILLISECONDS);
} else {
doEmptyWallet2(aesKey);
}
}
private void doEmptyWallet2(KeyParameter aesKey) {
emptyWalletButton.setDisable(true);
openOfferManager.closeAllOpenOffers(() -> {
openOfferManager.removeAllOpenOffers(() -> {
try {
walletService.emptyWallet(addressInputTextField.getText(),
aesKey,

View File

@ -23,6 +23,7 @@ import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.AddressEntryException;
import io.bitsquare.btc.Restrictions;
import io.bitsquare.btc.WalletService;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.handlers.FaultHandler;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.common.util.Tuple2;
@ -47,6 +48,8 @@ import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Coin;
import org.spongycastle.crypto.params.KeyParameter;
import java.util.concurrent.TimeUnit;
import static io.bitsquare.gui.util.FormBuilder.*;
public class BuyerStep5View extends TradeStepView {
@ -223,8 +226,6 @@ public class BuyerStep5View extends TradeStepView {
}
private void doWithdrawal(Coin receiverAmount) {
useSavingsWalletButton.setDisable(true);
withdrawToExternalWalletButton.setDisable(true);
String toAddress = withdrawAddressTextField.getText();
ResultHandler resultHandler = this::handleTradeCompleted;
FaultHandler faultHandler = (errorMessage, throwable) -> {
@ -236,17 +237,16 @@ public class BuyerStep5View extends TradeStepView {
new Popup().error(errorMessage).show();
};
if (model.dataModel.walletService.getWallet().isEncrypted()) {
model.dataModel.walletPasswordWindow.onAesKey(aesKey -> doWithdrawRequest(toAddress, receiverAmount, aesKey, resultHandler, faultHandler))
.onClose(() -> {
useSavingsWalletButton.setDisable(false);
withdrawToExternalWalletButton.setDisable(false);
})
.show();
UserThread.runAfter(() -> model.dataModel.walletPasswordWindow.onAesKey(aesKey ->
doWithdrawRequest(toAddress, receiverAmount, aesKey, resultHandler, faultHandler))
.show(), 300, TimeUnit.MILLISECONDS);
} else
doWithdrawRequest(toAddress, receiverAmount, null, resultHandler, faultHandler);
}
private void doWithdrawRequest(String toAddress, Coin receiverAmount, KeyParameter aesKey, ResultHandler resultHandler, FaultHandler faultHandler) {
useSavingsWalletButton.setDisable(true);
withdrawToExternalWalletButton.setDisable(true);
model.dataModel.onWithdrawRequest(toAddress,
receiverAmount,
aesKey,