Refactor persistence (arbitrator)

This commit is contained in:
Manfred Karrer 2015-03-24 18:18:16 +01:00
parent 917dd3522b
commit b807ee17a6
13 changed files with 210 additions and 233 deletions

View file

@ -17,78 +17,126 @@
package io.bitsquare.arbitration; package io.bitsquare.arbitration;
import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.persistence.Storage;
import io.bitsquare.user.User;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
import java.io.Serializable; import java.io.Serializable;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
public class Arbitrator implements Serializable { import javax.inject.Inject;
private static final long serialVersionUID = -2625059604136756635L;
public class Arbitrator implements Serializable {
private static final long serialVersionUID = 1L;
///////////////////////////////////////////////////////////////////////////////////////////
// Enums
///////////////////////////////////////////////////////////////////////////////////////////
public enum ID_TYPE {
REAL_LIFE_ID,
NICKNAME,
COMPANY
}
public enum METHOD {
TLS_NOTARY,
SKYPE_SCREEN_SHARING,
SMART_PHONE_VIDEO_CHAT,
REQUIRE_REAL_ID,
BANK_STATEMENT,
OTHER
}
public enum ID_VERIFICATION {
PASSPORT,
GOV_ID,
UTILITY_BILLS,
FACEBOOK,
GOOGLE_PLUS,
TWITTER,
PGP,
BTC_OTC,
OTHER
}
transient private Storage<Arbitrator> storage;
transient private boolean saveOnEveryUpdate;
// Persisted fields
private String id; private String id;
private String pubKeyAsHex;
private byte[] pubKey; private byte[] pubKey;
private String p2pSigPubKeyAsHex; private PublicKey p2pSigPubKey;
private String name; private String name;
private Reputation reputation;
// editable
private ID_TYPE idType; private ID_TYPE idType;
private List<Locale> languages; private List<Locale> languages;
private Reputation reputation;
private Coin fee; private Coin fee;
private List<METHOD> arbitrationMethods; private List<METHOD> arbitrationMethods;
private List<ID_VERIFICATION> idVerifications; private List<ID_VERIFICATION> idVerifications;
private String webUrl; private String webUrl;
private String description; private String description;
public Arbitrator() {
@Inject
public Arbitrator(Storage<Arbitrator> storage, User user) {
this.storage = storage;
Arbitrator persisted = storage.getPersisted(this);
if (persisted != null) {
//TODO for mock arbitrator
id = persisted.getName();
this.pubKey = persisted.getPubKey();
this.p2pSigPubKey = persisted.getP2pSigPubKey();
this.name = persisted.getName();
this.idType = persisted.getIdType();
this.languages = persisted.getLanguages();
this.reputation = persisted.getReputation();
this.fee = persisted.getFee();
this.arbitrationMethods = persisted.getArbitrationMethods();
this.idVerifications = persisted.getIdVerifications();
this.webUrl = persisted.getWebUrl();
this.description = persisted.getDescription();
}
else {
// Mock
id = "Manfred Karrer";
this.pubKey = new ECKey().getPubKey();
this.p2pSigPubKey = user.getP2PSigPubKey();
this.name = "Manfred Karrer";
this.idType = Arbitrator.ID_TYPE.REAL_LIFE_ID;
this.languages = Arrays.asList(LanguageUtil.getDefaultLanguageLocale());
this.reputation = new Reputation();
this.fee = Coin.parseCoin("0.1");
this.arbitrationMethods = Arrays.asList(Arbitrator.METHOD.TLS_NOTARY);
this.idVerifications = Arrays.asList(ID_VERIFICATION.PASSPORT);
this.webUrl = "https://bitsquare.io";
this.description = "Bla bla...";
doSave();
}
} }
public Arbitrator(byte[] pubKey, public void save() {
String p2pSigPubKeyAsHex, if (saveOnEveryUpdate)
String name, doSave();
ID_TYPE idType,
List<Locale> languages,
Reputation reputation,
Coin fee,
List<METHOD> arbitrationMethods,
List<ID_VERIFICATION> idVerifications,
String webUrl,
String description) {
this.pubKey = pubKey;
this.p2pSigPubKeyAsHex = p2pSigPubKeyAsHex;
this.name = name;
this.idType = idType;
this.languages = languages;
this.reputation = reputation;
this.fee = fee;
this.arbitrationMethods = arbitrationMethods;
this.idVerifications = idVerifications;
this.webUrl = webUrl;
this.description = description;
//TODO for mock arbitrator
id = name;
} }
public void applyPersistedArbitrator(Arbitrator persistedArbitrator) { private void doSave() {
this.pubKeyAsHex = persistedArbitrator.getPubKeyAsHex(); storage.save();
this.p2pSigPubKeyAsHex = persistedArbitrator.getPubKeyAsHex();
this.name = persistedArbitrator.getName();
this.idType = persistedArbitrator.getIdType();
this.languages = persistedArbitrator.getLanguages();
this.reputation = persistedArbitrator.getReputation();
this.fee = persistedArbitrator.getFee();
this.arbitrationMethods = persistedArbitrator.getArbitrationMethods();
this.idVerifications = persistedArbitrator.getIdVerifications();
this.webUrl = persistedArbitrator.getWebUrl();
this.description = persistedArbitrator.getDescription();
//TODO for mock arbitrator
id = name;
} }
@Override @Override
@ -114,20 +162,48 @@ public class Arbitrator implements Serializable {
return id != null && id.equals(other.getId()); return id != null && id.equals(other.getId());
} }
public String getId() {
return id; ///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setSaveOnEveryUpdate(boolean saveOnEveryUpdate) {
this.saveOnEveryUpdate = saveOnEveryUpdate;
} }
public String getPubKeyAsHex() { public void setDescription(String description) {
return pubKeyAsHex; this.description = description;
doSave();
} }
public byte[] getPubKey() { public void setIdType(ID_TYPE idType) {
return pubKey; this.idType = idType;
doSave();
} }
public String getP2pSigPubKeyAsHex() { public void setLanguages(List<Locale> languages) {
return p2pSigPubKeyAsHex; this.languages = languages;
doSave();
}
public void setFee(Coin fee) {
this.fee = fee;
doSave();
}
public void setArbitrationMethods(List<METHOD> arbitrationMethods) {
this.arbitrationMethods = arbitrationMethods;
doSave();
}
public void setIdVerifications(List<ID_VERIFICATION> idVerifications) {
this.idVerifications = idVerifications;
doSave();
}
public void setWebUrl(String webUrl) {
this.webUrl = webUrl;
doSave();
} }
@ -135,6 +211,17 @@ public class Arbitrator implements Serializable {
// Getters // Getters
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public String getId() {
return id;
}
public byte[] getPubKey() {
return pubKey;
}
public PublicKey getP2pSigPubKey() {
return p2pSigPubKey;
}
public String getName() { public String getName() {
return name; return name;
@ -171,36 +258,4 @@ public class Arbitrator implements Serializable {
public String getDescription() { public String getDescription() {
return description; return description;
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Enums
///////////////////////////////////////////////////////////////////////////////////////////
public enum ID_TYPE {
REAL_LIFE_ID,
NICKNAME,
COMPANY
}
public enum METHOD {
TLS_NOTARY,
SKYPE_SCREEN_SHARING,
SMART_PHONE_VIDEO_CHAT,
REQUIRE_REAL_ID,
BANK_STATEMENT,
OTHER
}
public enum ID_VERIFICATION {
PASSPORT,
GOV_ID,
UTILITY_BILLS,
FACEBOOK,
GOOGLE_PLUS,
TWITTER,
PGP,
BTC_OTC,
OTHER
}
} }

View file

@ -18,9 +18,7 @@
package io.bitsquare.gui.main; package io.bitsquare.gui.main;
import io.bitsquare.app.UpdateProcess; import io.bitsquare.app.UpdateProcess;
import io.bitsquare.arbitration.Arbitrator;
import io.bitsquare.arbitration.ArbitratorService; import io.bitsquare.arbitration.ArbitratorService;
import io.bitsquare.arbitration.Reputation;
import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.btc.BitcoinNetwork;
import io.bitsquare.btc.WalletService; import io.bitsquare.btc.WalletService;
import io.bitsquare.common.viewfx.model.ViewModel; import io.bitsquare.common.viewfx.model.ViewModel;
@ -28,27 +26,18 @@ import io.bitsquare.fiat.FiatAccount;
import io.bitsquare.fiat.FiatAccountType; import io.bitsquare.fiat.FiatAccountType;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.CountryUtil; import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.p2p.BaseP2PService; import io.bitsquare.p2p.BaseP2PService;
import io.bitsquare.p2p.BootstrapState; import io.bitsquare.p2p.BootstrapState;
import io.bitsquare.p2p.ClientNode; import io.bitsquare.p2p.ClientNode;
import io.bitsquare.p2p.MessageService;
import io.bitsquare.persistence.Persistence; import io.bitsquare.persistence.Persistence;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeManager; import io.bitsquare.trade.TradeManager;
import io.bitsquare.user.AccountSettings; import io.bitsquare.user.AccountSettings;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import io.bitsquare.util.Utilities;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Currency; import java.util.Currency;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import javafx.application.Platform; import javafx.application.Platform;
@ -110,7 +99,7 @@ class MainViewModel implements ViewModel {
private AccountSettings accountSettings; private AccountSettings accountSettings;
@Inject @Inject
public MainViewModel(User user, WalletService walletService, ClientNode clientNode, MessageService messageService, public MainViewModel(User user, WalletService walletService, ClientNode clientNode,
ArbitratorService arbitratorService, ArbitratorService arbitratorService,
TradeManager tradeManager, BitcoinNetwork bitcoinNetwork, UpdateProcess updateProcess, TradeManager tradeManager, BitcoinNetwork bitcoinNetwork, UpdateProcess updateProcess,
BSFormatter formatter, Persistence persistence, AccountSettings accountSettings) { BSFormatter formatter, Persistence persistence, AccountSettings accountSettings) {
@ -129,7 +118,6 @@ class MainViewModel implements ViewModel {
updateProcess.state.addListener((observableValue, oldValue, newValue) -> applyUpdateState(newValue)); updateProcess.state.addListener((observableValue, oldValue, newValue) -> applyUpdateState(newValue));
applyUpdateState(updateProcess.state.get()); applyUpdateState(updateProcess.state.get());
user.currentFiatAccountProperty().addListener((observable, oldValue, newValue) -> persistence.write(user));
currentBankAccount.bind(user.currentFiatAccountProperty()); currentBankAccount.bind(user.currentFiatAccountProperty());
user.fiatAccountsObservableList().addListener((ListChangeListener<FiatAccount>) change -> { user.fiatAccountsObservableList().addListener((ListChangeListener<FiatAccount>) change -> {
bankAccountsComboBoxDisable.set(change.getList().isEmpty()); bankAccountsComboBoxDisable.set(change.getList().isEmpty());
@ -211,11 +199,6 @@ class MainViewModel implements ViewModel {
updateNumPendingTrades(); updateNumPendingTrades();
showAppScreen.set(true); showAppScreen.set(true);
// For alpha version
// uses messageService, so don't call it before backend is ready
if (accountSettings.getAcceptedArbitrators().isEmpty())
accountSettings.addAcceptedArbitrator(getMockArbitrator());
// For alpha version // For alpha version
if (!user.isRegistered()) { if (!user.isRegistered()) {
FiatAccount fiatAccount = new FiatAccount(FiatAccountType.IRC, FiatAccount fiatAccount = new FiatAccount(FiatAccountType.IRC,
@ -226,8 +209,6 @@ class MainViewModel implements ViewModel {
"Demo (E.g. IBAN) ", "Demo (E.g. IBAN) ",
"Demo (E.g. BIC) "); "Demo (E.g. BIC) ");
user.addFiatAccount(fiatAccount); user.addFiatAccount(fiatAccount);
persistence.write(user);
user.setAccountID(walletService.getRegistrationAddressEntry().toString()); user.setAccountID(walletService.getRegistrationAddressEntry().toString());
} }
@ -351,30 +332,4 @@ class MainViewModel implements ViewModel {
} }
} }
private Arbitrator getMockArbitrator() {
byte[] pubKey = new ECKey().getPubKey();
String p2pSigPubKeyAsHex = Utilities.getHexStringFromPublicKey(user.getP2PSigPubKey());
List<Locale> languages = new ArrayList<>();
languages.add(LanguageUtil.getDefaultLanguageLocale());
List<Arbitrator.METHOD> arbitrationMethods = new ArrayList<>();
arbitrationMethods.add(Arbitrator.METHOD.TLS_NOTARY);
List<Arbitrator.ID_VERIFICATION> idVerifications = new ArrayList<>();
idVerifications.add(Arbitrator.ID_VERIFICATION.PASSPORT);
idVerifications.add(Arbitrator.ID_VERIFICATION.GOV_ID);
Arbitrator arbitrator = new Arbitrator(pubKey,
p2pSigPubKeyAsHex,
"Manfred Karrer",
Arbitrator.ID_TYPE.REAL_LIFE_ID,
languages,
new Reputation(),
Coin.parseCoin("0.1"),
arbitrationMethods,
idVerifications,
"https://bitsquare.io",
"Bla bla...");
arbitratorService.addArbitrator(arbitrator);
return arbitrator;
}
} }

View file

@ -122,7 +122,6 @@ public class ArbitratorBrowserView extends ActivatableView<Pane, Void> implement
@FXML @FXML
public void onSelect() { public void onSelect() {
accountSettings.addAcceptedArbitrator(currentArbitrator); accountSettings.addAcceptedArbitrator(currentArbitrator);
persistence.write(accountSettings);
} }
@FXML @FXML

View file

@ -19,7 +19,6 @@ package io.bitsquare.gui.main.account.arbitrator.registration;
import io.bitsquare.arbitration.Arbitrator; import io.bitsquare.arbitration.Arbitrator;
import io.bitsquare.arbitration.ArbitratorService; import io.bitsquare.arbitration.ArbitratorService;
import io.bitsquare.arbitration.Reputation;
import io.bitsquare.btc.WalletService; import io.bitsquare.btc.WalletService;
import io.bitsquare.common.viewfx.view.ActivatableView; import io.bitsquare.common.viewfx.view.ActivatableView;
import io.bitsquare.common.viewfx.view.FxmlView; import io.bitsquare.common.viewfx.view.FxmlView;
@ -27,7 +26,6 @@ import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.BSResources; import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.LanguageUtil; import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import io.bitsquare.util.Utilities; import io.bitsquare.util.Utilities;
@ -79,18 +77,17 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
private List<Locale> languageList = new ArrayList<>(); private List<Locale> languageList = new ArrayList<>();
private List<Arbitrator.METHOD> methodList = new ArrayList<>(); private List<Arbitrator.METHOD> methodList = new ArrayList<>();
private List<Arbitrator.ID_VERIFICATION> idVerificationList = new ArrayList<>(); private List<Arbitrator.ID_VERIFICATION> idVerificationList = new ArrayList<>();
private Arbitrator arbitrator = new Arbitrator();
private final Persistence persistence; private final Arbitrator arbitrator;
private final WalletService walletService; private final WalletService walletService;
private final ArbitratorService messageService; private final ArbitratorService messageService;
private final User user; private final User user;
private final BSFormatter formatter; private final BSFormatter formatter;
@Inject @Inject
private ArbitratorRegistrationView(Persistence persistence, WalletService walletService, private ArbitratorRegistrationView(Arbitrator arbitrator, WalletService walletService,
ArbitratorService messageService, User user, BSFormatter formatter) { ArbitratorService messageService, User user, BSFormatter formatter) {
this.persistence = persistence; this.arbitrator = arbitrator;
this.walletService = walletService; this.walletService = walletService;
this.messageService = messageService; this.messageService = messageService;
this.user = user; this.user = user;
@ -101,15 +98,7 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
public void initialize() { public void initialize() {
accordion.setExpandedPane(profileTitledPane); accordion.setExpandedPane(profileTitledPane);
Arbitrator persistedArbitrator = (Arbitrator) persistence.read(arbitrator);
if (persistedArbitrator != null) {
arbitrator.applyPersistedArbitrator(persistedArbitrator);
applyArbitrator(); applyArbitrator();
}
else {
languageList.add(LanguageUtil.getDefaultLanguageLocale());
languagesTextField.setText(formatter.languageLocalesToString(languageList));
}
languageComboBox.setItems(FXCollections.observableArrayList(LanguageUtil.getAllLanguageLocales())); languageComboBox.setItems(FXCollections.observableArrayList(LanguageUtil.getAllLanguageLocales()));
languageComboBox.setConverter(new StringConverter<Locale>() { languageComboBox.setConverter(new StringConverter<Locale>() {
@ -255,9 +244,16 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
@FXML @FXML
public void onSaveProfile() { public void onSaveProfile() {
arbitrator = getEditedArbitrator(); arbitrator.setSaveOnEveryUpdate(false);
if (arbitrator != null) { arbitrator.setWebUrl(webPageTextField.getText());
persistence.write(arbitrator); arbitrator.setFee(formatter.parseToCoin(arbitrationFeeTextField.getText()));
arbitrator.setIdType(idType);
arbitrator.setIdVerifications(idVerificationList);
arbitrator.setLanguages(languageList);
arbitrator.setArbitrationMethods(methodList);
arbitrator.setSaveOnEveryUpdate(true);
arbitrator.save();
if (isEditMode) { if (isEditMode) {
close(); close();
@ -266,7 +262,6 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
setupPaySecurityDepositScreen(); setupPaySecurityDepositScreen();
accordion.setExpandedPane(paySecurityDepositTitledPane); accordion.setExpandedPane(paySecurityDepositTitledPane);
} }
}
messageService.addArbitrator(arbitrator); messageService.addArbitrator(arbitrator);
} }
@ -366,27 +361,6 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
} }
} }
private Arbitrator getEditedArbitrator() {
byte[] pubKey = walletService.getArbitratorDepositAddressEntry().getPubKey();
String p2pSigPubKeyAsHex = Utilities.getHexStringFromPublicKey(user.getP2PSigPubKey());
String name = nameTextField.getText();
Coin fee = formatter.parseToCoin(arbitrationFeeTextField.getText());
String webUrl = webPageTextField.getText();
String description = descriptionTextArea.getText();
return new Arbitrator(pubKey,
p2pSigPubKeyAsHex,
name,
idType,
languageList,
new Reputation(),
fee,
methodList,
idVerificationList,
webUrl,
description);
}
private void close() { private void close() {
Stage stage = (Stage) root.getScene().getWindow(); Stage stage = (Stage) root.getScene().getWindow();
stage.close(); stage.close();

View file

@ -95,7 +95,6 @@ class FiatAccountDataModel implements Activatable, DataModel {
primaryID.get(), primaryID.get(),
secondaryID.get()); secondaryID.get());
user.addFiatAccount(fiatAccount); user.addFiatAccount(fiatAccount);
saveUser();
allFiatAccounts.setAll(user.fiatAccountsObservableList()); allFiatAccounts.setAll(user.fiatAccountsObservableList());
countryNotInAcceptedCountriesList.set(!accountSettings.getAcceptedCountries().contains(country.get())); countryNotInAcceptedCountriesList.set(!accountSettings.getAcceptedCountries().contains(country.get()));
reset(); reset();
@ -103,7 +102,6 @@ class FiatAccountDataModel implements Activatable, DataModel {
void removeBankAccount() { void removeBankAccount() {
user.removeFiatAccount(user.currentFiatAccountProperty().get()); user.removeFiatAccount(user.currentFiatAccountProperty().get());
saveUser();
allFiatAccounts.setAll(user.fiatAccountsObservableList()); allFiatAccounts.setAll(user.fiatAccountsObservableList());
reset(); reset();
} }
@ -112,13 +110,11 @@ class FiatAccountDataModel implements Activatable, DataModel {
// already added it before // already added it before
void addCountryToAcceptedCountriesList() { void addCountryToAcceptedCountriesList() {
accountSettings.addAcceptedCountry(country.get()); accountSettings.addAcceptedCountry(country.get());
saveSettings();
countryNotInAcceptedCountriesList.set(false); countryNotInAcceptedCountriesList.set(false);
} }
void selectBankAccount(FiatAccount fiatAccount) { void selectBankAccount(FiatAccount fiatAccount) {
user.setCurrentFiatAccount(fiatAccount); user.setCurrentFiatAccount(fiatAccount);
persistence.write(user);
if (fiatAccount != null) { if (fiatAccount != null) {
title.set(fiatAccount.getNameOfBank()); title.set(fiatAccount.getNameOfBank());
@ -177,12 +173,4 @@ class FiatAccountDataModel implements Activatable, DataModel {
country.set(null); country.set(null);
currency.set(null); currency.set(null);
} }
private void saveUser() {
persistence.write(user);
}
private void saveSettings() {
persistence.write(accountSettings);
}
} }

View file

@ -84,7 +84,6 @@ class IrcAccountDataModel implements Activatable, DataModel {
"irc", "irc",
"irc"); "irc");
user.addFiatAccount(fiatAccount); user.addFiatAccount(fiatAccount);
saveUser();
allFiatAccounts.setAll(user.fiatAccountsObservableList()); allFiatAccounts.setAll(user.fiatAccountsObservableList());
reset(); reset();
} }
@ -103,8 +102,4 @@ class IrcAccountDataModel implements Activatable, DataModel {
type.set(null); type.set(null);
currency.set(null); currency.set(null);
} }
private void saveUser() {
persistence.write(user);
}
} }

View file

@ -69,7 +69,6 @@ class RestrictionsDataModel implements Activatable, DataModel {
@Override @Override
public void deactivate() { public void deactivate() {
// no-op
} }
ObservableList<Country> getAllCountriesFor(Region selectedRegion) { ObservableList<Country> getAllCountriesFor(Region selectedRegion) {
@ -90,14 +89,12 @@ class RestrictionsDataModel implements Activatable, DataModel {
void removeLanguage(Locale locale) { void removeLanguage(Locale locale) {
languageList.remove(locale); languageList.remove(locale);
accountSettings.removeAcceptedLanguageLocale(locale); accountSettings.removeAcceptedLanguageLocale(locale);
saveSettings();
} }
void addCountry(Country country) { void addCountry(Country country) {
if (!countryList.contains(country) && country != null) { if (!countryList.contains(country) && country != null) {
countryList.add(country); countryList.add(country);
accountSettings.addAcceptedCountry(country); accountSettings.addAcceptedCountry(country);
saveSettings();
} }
} }
@ -106,24 +103,16 @@ class RestrictionsDataModel implements Activatable, DataModel {
// In addAcceptedCountry there is a check to no add duplicates, so it works correctly for now // In addAcceptedCountry there is a check to no add duplicates, so it works correctly for now
CountryUtil.getAllEuroCountries().stream().forEach(accountSettings::addAcceptedCountry); CountryUtil.getAllEuroCountries().stream().forEach(accountSettings::addAcceptedCountry);
countryList.setAll(accountSettings.getAcceptedCountries()); countryList.setAll(accountSettings.getAcceptedCountries());
saveSettings();
return countryList; return countryList;
} }
void removeCountry(Country country) { void removeCountry(Country country) {
countryList.remove(country); countryList.remove(country);
accountSettings.removeAcceptedCountry(country); accountSettings.removeAcceptedCountry(country);
saveSettings();
} }
void removeArbitrator(Arbitrator arbitrator) { void removeArbitrator(Arbitrator arbitrator) {
arbitratorList.remove(arbitrator); arbitratorList.remove(arbitrator);
accountSettings.removeAcceptedArbitrator(arbitrator); accountSettings.removeAcceptedArbitrator(arbitrator);
saveSettings();
}
private void saveSettings() {
persistence.write(accountSettings);
} }
} }

View file

@ -23,8 +23,11 @@ import io.bitsquare.util.FileUtil;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InvalidClassException;
import java.io.Serializable; import java.io.Serializable;
import java.nio.file.Paths;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
@ -70,7 +73,23 @@ public class Storage<T extends Serializable> {
throw new RuntimeException("storageFile = null. Call init before using read/write."); throw new RuntimeException("storageFile = null. Call init before using read/write.");
try { try {
return (T) FileUtil.read(storageFile); T persistedObject = (T) FileUtil.read(storageFile);
// If we did not get any exception we can be sure the data are consistent so we make a backup
FileUtil.backupFile(storageFile, new File(Paths.get(dir.getAbsolutePath(), "backups").toString()),
serializable.getClass().getSimpleName() + ".ser");
return persistedObject;
} catch (InvalidClassException e) {
log.error("Version of persisted class has changed. We cannot read the persisted data anymore. We make a backup and remove the inconsistent file.");
try {
// In case the persisted data have been critical (keys) we keep a backup which might be used for recovery
FileUtil.removeAndBackupFile(storageFile, new File(Paths.get(dir.getAbsolutePath(), "inconsistent").toString()),
serializable.getClass().getSimpleName() + ".ser");
} catch (IOException e1) {
e1.printStackTrace();
log.error(e1.getMessage());
// We swallow Exception if backup fails
}
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
log.info("File not available. That is OK for the first run."); log.info("File not available. That is OK for the first run.");
} catch (IOException | ClassNotFoundException e) { } catch (IOException | ClassNotFoundException e) {

View file

@ -59,8 +59,8 @@ public class Contract implements Serializable {
this.takerAccountID = takerAccountID; this.takerAccountID = takerAccountID;
this.offererFiatAccount = offererFiatAccount; this.offererFiatAccount = offererFiatAccount;
this.takerFiatAccount = takerFiatAccount; this.takerFiatAccount = takerFiatAccount;
this.offererP2PSigPubKeyAsString = Utilities.getHexStringFromPublicKey(offererP2PSigPubKey); this.offererP2PSigPubKeyAsString = Utilities.getHexFromPubKey(offererP2PSigPubKey);
this.takerP2PSigPubKeyAsString = Utilities.getHexStringFromPublicKey(takerP2PSigPubKey); this.takerP2PSigPubKeyAsString = Utilities.getHexFromPubKey(takerP2PSigPubKey);
} }

View file

@ -45,13 +45,12 @@ public class AccountSettings implements Serializable {
private List<Country> acceptedCountryLocales = new ArrayList<>(); private List<Country> acceptedCountryLocales = new ArrayList<>();
private List<Arbitrator> acceptedArbitrators = new ArrayList<>(); private List<Arbitrator> acceptedArbitrators = new ArrayList<>();
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Constructor // Constructor
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Inject @Inject
public AccountSettings(Storage<AccountSettings> storage) { public AccountSettings(Storage<AccountSettings> storage, Arbitrator defaultArbitrator) {
this.storage = storage; this.storage = storage;
AccountSettings persisted = storage.getPersisted(this); AccountSettings persisted = storage.getPersisted(this);
@ -63,7 +62,7 @@ public class AccountSettings implements Serializable {
else { else {
acceptedLanguageLocales = Arrays.asList(LanguageUtil.getDefaultLanguageLocale(), LanguageUtil.getEnglishLanguageLocale()); acceptedLanguageLocales = Arrays.asList(LanguageUtil.getDefaultLanguageLocale(), LanguageUtil.getEnglishLanguageLocale());
acceptedCountryLocales = Arrays.asList(CountryUtil.getDefaultCountry()); acceptedCountryLocales = Arrays.asList(CountryUtil.getDefaultCountry());
acceptedArbitrators = new ArrayList<>(); acceptedArbitrators = Arrays.asList(defaultArbitrator);
} }
} }

View file

@ -20,6 +20,8 @@ package io.bitsquare.util;
import org.bitcoinj.core.Utils; import org.bitcoinj.core.Utils;
import org.bitcoinj.utils.Threading; import org.bitcoinj.utils.Threading;
import com.google.common.io.Files;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -117,4 +119,18 @@ public class FileUtil {
lock.unlock(); lock.unlock();
} }
} }
public static void removeAndBackupFile(File storageFile, File dir, String name) throws IOException {
if (!dir.exists())
dir.mkdir();
writeTempFileToFile(storageFile, new File(dir, name));
}
public static void backupFile(File storageFile, File dir, String name) throws IOException {
if (!dir.exists())
dir.mkdir();
Files.copy(storageFile, new File(dir, name));
}
} }

View file

@ -295,7 +295,7 @@ public class Utilities {
return animationTimer; return animationTimer;
} }
public static String getHexStringFromPublicKey(PublicKey publicKey) { public static String getHexFromPubKey(PublicKey publicKey) {
final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded()); final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
return Utils.HEX.encode(x509EncodedKeySpec.getEncoded()); return Utils.HEX.encode(x509EncodedKeySpec.getEncoded());
} }

View file

@ -17,17 +17,10 @@
package io.bitsquare.trade.protocol.placeoffer; package io.bitsquare.trade.protocol.placeoffer;
import io.bitsquare.arbitration.Arbitrator;
import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.btc.BitcoinNetwork;
import io.bitsquare.btc.FeePolicy; import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.UserAgent; import io.bitsquare.btc.UserAgent;
import io.bitsquare.btc.WalletService; import io.bitsquare.btc.WalletService;
import io.bitsquare.crypto.EncryptionService;
import io.bitsquare.fiat.FiatAccountType;
import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.offer.Direction;
import io.bitsquare.offer.Offer;
import io.bitsquare.offer.OfferBookService; import io.bitsquare.offer.OfferBookService;
import io.bitsquare.offer.tomp2p.TomP2POfferBookService; import io.bitsquare.offer.tomp2p.TomP2POfferBookService;
import io.bitsquare.p2p.BootstrapState; import io.bitsquare.p2p.BootstrapState;
@ -40,16 +33,11 @@ import io.bitsquare.persistence.Persistence;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import org.bitcoinj.core.Address; import org.bitcoinj.core.Address;
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Threading; import org.bitcoinj.utils.Threading;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Currency;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import org.junit.After; import org.junit.After;
@ -301,7 +289,7 @@ public class PlaceOfferProtocolTest {
faultHandler); faultHandler);
}*/ }*/
private Offer getOffer() throws NoSuchAlgorithmException { /* private Offer getOffer() throws NoSuchAlgorithmException {
return new Offer(OFFER_ID, return new Offer(OFFER_ID,
new EncryptionService().getGeneratedDSAKeyPair().getPublic(), new EncryptionService().getGeneratedDSAKeyPair().getPublic(),
Direction.BUY, Direction.BUY,
@ -317,5 +305,5 @@ public class PlaceOfferProtocolTest {
Arrays.asList(CountryUtil.getDefaultCountry()), Arrays.asList(CountryUtil.getDefaultCountry()),
Arrays.asList(LanguageUtil.getDefaultLanguageLocale()) Arrays.asList(LanguageUtil.getDefaultLanguageLocale())
); );
} }*/
} }