Release 4.4.3 (#415)

* Add ability for change password for wallets classes.

* Update generateWalletPassword

* Add WalletLoadingService

* Add update monero password after wallet loading.

* Update version for Cake Wallet to 4.4.2 (103)

* Changed version for Cake Wallet to 4.4.3 (104).

* Changed version for Cake Wallet android

* Changed version for Monero.com ios and android.
This commit is contained in:
mkyq 2022-07-19 15:29:28 +01:00 committed by GitHub
parent 8fec3272cf
commit b72443a8c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 214 additions and 41 deletions

View file

@ -24,7 +24,7 @@ abstract class ElectrumTransactionHistoryBase
}
final WalletInfo walletInfo;
final String _password;
String _password;
int _height;
Future<void> init() async => await _load();
@ -51,6 +51,11 @@ abstract class ElectrumTransactionHistoryBase
}
}
Future<void> changePassword(String password) async {
_password = password;
await save();
}
Future<Map<String, Object>> _read() async {
final dirPath =
await pathForWalletDir(name: walletInfo.name, type: walletInfo.type);

View file

@ -109,7 +109,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
BitcoinWalletKeys get keys => BitcoinWalletKeys(
wif: hd.wif, privateKey: hd.privKey, publicKey: hd.pubKey);
final String _password;
String _password;
List<BitcoinUnspent> unspentCoins;
List<int> _feeRates;
Map<String, BehaviorSubject<Object>> _scripthashesUpdateSubject;
@ -392,6 +392,13 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
await transactionHistory.save();
}
@override
Future<void> changePassword(String password) async {
_password = password;
await save();
await transactionHistory.changePassword(password);
}
bitcoin.ECPair keyPairFor({@required int index}) =>
generateKeyPair(hd: hd, index: index, network: networkType);

View file

@ -69,4 +69,6 @@ abstract class WalletBase<
Future<void> rescan({int height});
void close();
Future<void> changePassword(String password);
}

View file

@ -565,6 +565,16 @@ extern "C"
store_lock.unlock();
}
bool set_password(char *password, Utf8Box &error) {
bool is_changed = get_current_wallet()->setPassword(std::string(password));
if (!is_changed) {
error = Utf8Box(strdup(get_current_wallet()->errorString().c_str()));
}
return is_changed;
}
bool transaction_create(char *address, char *asset_type, char *payment_id, char *amount,
uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction)
{

View file

@ -51,6 +51,8 @@ typedef set_recovering_from_seed = Void Function(Int8);
typedef store_c = Void Function(Pointer<Utf8>);
typedef set_password = Int8 Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
typedef set_listener = Void Function();
typedef get_syncing_height = Int64 Function();

View file

@ -51,6 +51,8 @@ typedef SetRecoveringFromSeed = void Function(int);
typedef Store = void Function(Pointer<Utf8>);
typedef SetPassword = int Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
typedef SetListener = void Function();
typedef GetSyncingHeight = int Function();

View file

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'package:cw_haven/api/structs/ut8_box.dart';
import 'package:cw_haven/api/convert_utf8_to_string.dart';
import 'package:cw_haven/api/signatures.dart';
import 'package:cw_haven/api/types.dart';
@ -67,6 +68,9 @@ final setRecoveringFromSeedNative = havenApi
final storeNative =
havenApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
final setPasswordNative =
havenApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>();
final setListenerNative = havenApi
.lookup<NativeFunction<set_listener>>('set_listener')
.asFunction<SetListener>();
@ -193,6 +197,21 @@ void storeSync() {
free(pathPointer);
}
void setPasswordSync(String password) {
final passwordPointer = Utf8.toUtf8(password);
final errorMessagePointer = allocate<Utf8Box>();
final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0;
free(passwordPointer);
if (!changed) {
final message = errorMessagePointer.ref.getValue();
free(errorMessagePointer);
throw Exception(message);
}
free(errorMessagePointer);
}
void closeCurrentWallet() => closeCurrentWalletNative();
String getSecretViewKey() =>

View file

@ -240,6 +240,11 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
await haven_wallet.store();
}
@override
Future<void> changePassword(String password) async {
haven_wallet.setPasswordSync(password);
}
Future<int> getNodeHeight() async => haven_wallet.getNodeHeight();
Future<bool> isConnected() async => haven_wallet.isConnected();

View file

@ -467,6 +467,16 @@ extern "C"
store_lock.unlock();
}
bool set_password(char *password, Utf8Box &error) {
bool is_changed = get_current_wallet()->setPassword(std::string(password));
if (!is_changed) {
error = Utf8Box(strdup(get_current_wallet()->errorString().c_str()));
}
return is_changed;
}
bool transaction_create(char *address, char *payment_id, char *amount,
uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction)
{

View file

@ -47,6 +47,8 @@ typedef set_recovering_from_seed = Void Function(Int8);
typedef store_c = Void Function(Pointer<Utf8>);
typedef set_password = Int8 Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
typedef set_listener = Void Function();
typedef get_syncing_height = Int64 Function();

View file

@ -47,6 +47,8 @@ typedef SetRecoveringFromSeed = void Function(int);
typedef Store = void Function(Pointer<Utf8>);
typedef SetPassword = int Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
typedef SetListener = void Function();
typedef GetSyncingHeight = int Function();

View file

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'package:cw_monero/api/structs/ut8_box.dart';
import 'package:cw_monero/api/convert_utf8_to_string.dart';
import 'package:cw_monero/api/signatures.dart';
import 'package:cw_monero/api/types.dart';
@ -67,6 +68,9 @@ final setRecoveringFromSeedNative = moneroApi
final storeNative =
moneroApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
final setPasswordNative =
moneroApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>();
final setListenerNative = moneroApi
.lookup<NativeFunction<set_listener>>('set_listener')
.asFunction<SetListener>();
@ -197,6 +201,21 @@ void storeSync() {
free(pathPointer);
}
void setPasswordSync(String password) {
final passwordPointer = Utf8.toUtf8(password);
final errorMessagePointer = allocate<Utf8Box>();
final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0;
free(passwordPointer);
if (!changed) {
final message = errorMessagePointer.ref.getValue();
free(errorMessagePointer);
throw Exception(message);
}
free(errorMessagePointer);
}
void closeCurrentWallet() => closeCurrentWalletNative();
String getSecretViewKey() =>

View file

@ -258,6 +258,11 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
await monero_wallet.store();
}
@override
Future<void> changePassword(String password) async {
monero_wallet.setPasswordSync(password);
}
Future<int> getNodeHeight() async => monero_wallet.getNodeHeight();
Future<bool> isConnected() async => monero_wallet.isConnected();

View file

@ -1,12 +1,6 @@
import 'package:uuid/uuid.dart';
import 'package:cw_core/key.dart';
import 'package:cw_core/wallet_type.dart';
String generateWalletPassword(WalletType type) {
switch (type) {
case WalletType.monero:
return Uuid().v4();
default:
return generateKey();
}
String generateWalletPassword() {
return generateKey();
}

View file

@ -1,5 +1,6 @@
import 'package:cake_wallet/di.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart';
@ -31,6 +32,8 @@ class WalletCreationService {
final Box<WalletInfo> walletInfoSource;
WalletService _service;
static const _isNewMoneroWalletPasswordUpdated = true;
void changeWalletType({@required WalletType type}) {
this.type = type;
_service = getIt.get<WalletService>(param1: type);
@ -51,28 +54,55 @@ class WalletCreationService {
Future<WalletBase> create(WalletCredentials credentials) async {
checkIfExists(credentials.name);
final password = generateWalletPassword(type);
final password = generateWalletPassword();
credentials.password = password;
await keyService.saveWalletPassword(
password: password, walletName: credentials.name);
return await _service.create(credentials);
final wallet = await _service.create(credentials);
if (wallet.type == WalletType.monero) {
await sharedPreferences
.setBool(
PreferencesKey.moneroWalletUpdateV1Key(wallet.name),
_isNewMoneroWalletPasswordUpdated);
}
return wallet;
}
Future<WalletBase> restoreFromKeys(WalletCredentials credentials) async {
checkIfExists(credentials.name);
final password = generateWalletPassword(type);
final password = generateWalletPassword();
credentials.password = password;
await keyService.saveWalletPassword(
password: password, walletName: credentials.name);
return await _service.restoreFromKeys(credentials);
final wallet = await _service.restoreFromKeys(credentials);
if (wallet.type == WalletType.monero) {
await sharedPreferences
.setBool(
PreferencesKey.moneroWalletUpdateV1Key(wallet.name),
_isNewMoneroWalletPasswordUpdated);
}
return wallet;
}
Future<WalletBase> restoreFromSeed(WalletCredentials credentials) async {
checkIfExists(credentials.name);
final password = generateWalletPassword(type);
final password = generateWalletPassword();
credentials.password = password;
await keyService.saveWalletPassword(
password: password, walletName: credentials.name);
return await _service.restoreFromSeed(credentials);
final wallet = await _service.restoreFromSeed(credentials);
if (wallet.type == WalletType.monero) {
await sharedPreferences
.setBool(
PreferencesKey.moneroWalletUpdateV1Key(wallet.name),
_isNewMoneroWalletPasswordUpdated);
}
return wallet;
}
}

View file

@ -0,0 +1,52 @@
import 'package:cake_wallet/core/generate_wallet_password.dart';
import 'package:cake_wallet/core/key_service.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:shared_preferences/shared_preferences.dart';
class WalletLoadingService {
WalletLoadingService(
this.sharedPreferences,
this.keyService,
this.walletServiceFactory);
final SharedPreferences sharedPreferences;
final KeyService keyService;
final WalletService Function(WalletType type) walletServiceFactory;
Future<WalletBase> load(WalletType type, String name) async {
if (walletServiceFactory == null) {
throw Exception('WalletLoadingService.walletServiceFactory is not set');
}
final walletService = walletServiceFactory?.call(type);
final password = await keyService.getWalletPassword(walletName: name);
final wallet = await walletService.openWallet(name, password);
if (type == WalletType.monero) {
await upateMoneroWalletPassword(wallet);
}
return wallet;
}
Future<void> upateMoneroWalletPassword(WalletBase wallet) async {
final key = PreferencesKey.moneroWalletUpdateV1Key(wallet.name);
var isPasswordUpdated = sharedPreferences.getBool(key) ?? false;
if (isPasswordUpdated) {
return;
}
final password = generateWalletPassword();
// Save new generated password with backup key for case
// if wallet will change password, but it will faild to updated in secure storage
final bakWalletName = '#__${wallet.name}_bak__#';
await keyService.saveWalletPassword(walletName: bakWalletName, password: password);
await wallet.changePassword(password);
await keyService.saveWalletPassword(walletName: wallet.name, password: password);
isPasswordUpdated = true;
await sharedPreferences.setBool(key, isPasswordUpdated);
}
}

View file

@ -124,6 +124,7 @@ import 'package:cake_wallet/exchange/exchange_template.dart';
import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart';
import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart';
import 'package:cake_wallet/core/wallet_loading_service.dart';
final getIt = GetIt.instance;
@ -218,6 +219,12 @@ Future setup(
sharedPreferences: getIt.get<SharedPreferences>(),
walletInfoSource: _walletInfoSource));
getIt.registerFactory<WalletLoadingService>(
() => WalletLoadingService(
getIt.get<SharedPreferences>(),
getIt.get<KeyService>(),
(WalletType type) => getIt.get<WalletService>(param1: type)));
getIt.registerFactoryParam<WalletNewVM, WalletType, void>((type, _) =>
WalletNewVM(getIt.get<AppStore>(),
getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
@ -352,7 +359,7 @@ Future setup(
getIt.registerFactory(() => WalletListViewModel(
_walletInfoSource,
getIt.get<AppStore>(),
getIt.get<KeyService>()));
getIt.get<WalletLoadingService>()));
getIt.registerFactory(() =>
WalletListPage(walletListViewModel: getIt.get<WalletListViewModel>()));

View file

@ -5,6 +5,7 @@ import 'package:cake_wallet/core/key_service.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/core/wallet_loading_service.dart';
Future<void> loadCurrentWallet() async {
final appStore = getIt.get<AppStore>();
@ -15,9 +16,7 @@ Future<void> loadCurrentWallet() async {
getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType) ??
0;
final type = deserializeFromInt(typeRaw);
final password =
await getIt.get<KeyService>().getWalletPassword(walletName: name);
final _service = getIt.get<WalletService>(param1: type);
final wallet = await _service.openWallet(name, password);
final walletLoadingService = getIt.get<WalletLoadingService>();
final wallet = await walletLoadingService.load(type, name);
appStore.changeCurrentWallet(wallet);
}

View file

@ -22,4 +22,8 @@ class PreferencesKey {
static const bitcoinTransactionPriority = 'current_fee_priority_bitcoin';
static const shouldShowReceiveWarning = 'should_show_receive_warning';
static const shouldShowYatPopup = 'should_show_yat_popup';
static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1';
static String moneroWalletUpdateV1Key(String name)
=> '${PreferencesKey.moneroWalletPasswordUpdateV1Base}_${name}';
}

View file

@ -1,9 +1,9 @@
import 'package:cake_wallet/core/wallet_loading_service.dart';
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/core/key_service.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
import 'package:cw_core/wallet_info.dart';
@ -16,7 +16,7 @@ class WalletListViewModel = WalletListViewModelBase with _$WalletListViewModel;
abstract class WalletListViewModelBase with Store {
WalletListViewModelBase(this._walletInfoSource, this._appStore,
this._keyService) {
this._walletLoadingService) {
wallets = ObservableList<WalletListItem>();
_updateList();
}
@ -26,17 +26,14 @@ abstract class WalletListViewModelBase with Store {
final AppStore _appStore;
final Box<WalletInfo> _walletInfoSource;
final KeyService _keyService;
final WalletLoadingService _walletLoadingService;
WalletType get currentWalletType => _appStore.wallet.type;
@action
Future<void> loadWallet(WalletListItem wallet) async {
final password =
await _keyService.getWalletPassword(walletName: wallet.name);
final walletService = getIt.get<WalletService>(param1: wallet.type);
final loadedWallet = await walletService.openWallet(wallet.name, password);
_appStore.changeCurrentWallet(loadedWallet);
Future<void> loadWallet(WalletListItem walletItem) async {
final wallet = await _walletLoadingService.load(walletItem.type, walletItem.name);
_appStore.changeCurrentWallet(wallet);
_updateList();
}

View file

@ -45,7 +45,7 @@ abstract class WalletRestorationFromKeysVMBase extends WalletCreationVM
@override
WalletCredentials getCredentials(dynamic options) {
final password = generateWalletPassword(type);
final password = generateWalletPassword();
switch (type) {
case WalletType.monero:

View file

@ -36,7 +36,7 @@ abstract class WalletRestorationFromSeedVMBase extends WalletCreationVM
@override
WalletCredentials getCredentials(dynamic options) {
final password = generateWalletPassword(type);
final password = generateWalletPassword();
switch (type) {
case WalletType.monero:

View file

@ -53,7 +53,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
@override
WalletCredentials getCredentials(dynamic options) {
final password = generateWalletPassword(type);
final password = generateWalletPassword();
final height = options['height'] as int;
name = options['name'] as String;

View file

@ -14,14 +14,14 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_ANDROID_TYPE=$1
MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.0.6"
MONERO_COM_BUILD_NUMBER=13
MONERO_COM_VERSION="1.0.7"
MONERO_COM_BUILD_NUMBER=14
MONERO_COM_BUNDLE_ID="com.monero.app"
MONERO_COM_PACKAGE="com.monero.app"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.4.1"
CAKEWALLET_BUILD_NUMBER=104
CAKEWALLET_VERSION="4.4.3"
CAKEWALLET_BUILD_NUMBER=105
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"

View file

@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_IOS_TYPE=$1
MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.0.6"
MONERO_COM_BUILD_NUMBER=16
MONERO_COM_VERSION="1.0.7"
MONERO_COM_BUILD_NUMBER=17
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.4.1"
CAKEWALLET_BUILD_NUMBER=100
CAKEWALLET_VERSION="4.4.3"
CAKEWALLET_BUILD_NUMBER=104
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
HAVEN_NAME="Haven"