From fc853dc55d24126fb28859a08233b5d78f6d34f6 Mon Sep 17 00:00:00 2001 From: pokkst Date: Tue, 5 Dec 2023 04:04:58 -0600 Subject: [PATCH] WIP: Polyseed. Polyseed wallets currently have offsets enforced due to a bug in ANONERO's polyseed implementation --- app/CMakeLists.txt | 15 +++ app/src/main/cpp/monerujo.cpp | 108 +++++++++++++++++- .../onboarding/OnboardingFragment.java | 11 ++ .../onboarding/OnboardingViewModel.java | 39 +++++-- .../java/net/mynero/wallet/model/Wallet.java | 43 ++++++- .../mynero/wallet/model/WalletManager.java | 26 +++++ .../main/res/layout/fragment_onboarding.xml | 34 +++--- app/src/main/res/values/strings.xml | 2 + external-libs/android32.Dockerfile | 21 ++++ external-libs/android32_x86.Dockerfile | 21 ++++ external-libs/android64.Dockerfile | 21 ++++ external-libs/android64_x86.Dockerfile | 21 ++++ external-libs/include/wallet2_api.h | 25 ++++ 13 files changed, 358 insertions(+), 29 deletions(-) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 08904bf..d2bce3e 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -79,6 +79,14 @@ add_library(wallet STATIC IMPORTED) set_target_properties(wallet PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/monero/libwallet.a) +add_library(polyseed STATIC IMPORTED) +set_target_properties(polyseed PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/libpolyseed.a) + +add_library(polyseed-wrapper STATIC IMPORTED) +set_target_properties(polyseed-wrapper PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/monero/libpolyseed_wrapper.a) + add_library(cryptonote_core STATIC IMPORTED) set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/monero/libcryptonote_core.a) @@ -155,6 +163,10 @@ add_library(net STATIC IMPORTED) set_target_properties(net PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/monero/libnet.a) +add_library(utf8proc STATIC IMPORTED) +set_target_properties(utf8proc PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/libutf8proc.a) + add_library(hardforks STATIC IMPORTED) set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/monero/libhardforks.a) @@ -198,6 +210,9 @@ target_link_libraries( monerujo cryptonote_core cryptonote_basic cryptonote_format_utils_basic + polyseed + polyseed-wrapper + utf8proc mnemonics ringct ringct_basic diff --git a/app/src/main/cpp/monerujo.cpp b/app/src/main/cpp/monerujo.cpp index eb73232..5b29960 100644 --- a/app/src/main/cpp/monerujo.cpp +++ b/app/src/main/cpp/monerujo.cpp @@ -347,6 +347,41 @@ Java_net_mynero_wallet_model_WalletManager_createWalletJ(JNIEnv *env, jobject in return reinterpret_cast(wallet); } +JNIEXPORT jlong JNICALL +Java_net_mynero_wallet_model_WalletManager_createWalletPolyseedJ(JNIEnv *env, jobject instance, + jstring path, jstring password, jstring passpharse, + jstring language, + jint networkType) { + std::string seed_words; + std::string err; + bool _polyseedCreate = Monero::Wallet::createPolyseed(seed_words, err); + if (!_polyseedCreate) { + LOGE("Failed to polyseedCreate"); + } + + // wallet->createPolyseed(seed_words, err); + + const char *_path = env->GetStringUTFChars(path, nullptr); + const char *_password = env->GetStringUTFChars(password, nullptr); + const char *_passpharse = env->GetStringUTFChars(passpharse, nullptr); + const char *_language = env->GetStringUTFChars(language, nullptr); // NOT USED ANYMORE????? + Monero::NetworkType _networkType = static_cast(networkType); + Monero::Wallet *wallet = + Monero::WalletManagerFactory::getWalletManager()->createWalletFromPolyseed( + std::string(_path), + std::string(_password), + _networkType, + seed_words, + std::string(_passpharse), true); + + env->ReleaseStringUTFChars(path, _path); + env->ReleaseStringUTFChars(password, _password); + env->ReleaseStringUTFChars(language, _language); + env->ReleaseStringUTFChars(passpharse, _passpharse); + return reinterpret_cast(wallet); +} + + JNIEXPORT jlong JNICALL Java_net_mynero_wallet_model_WalletManager_openWalletJ(JNIEnv *env, jobject instance, jstring path, jstring password, @@ -395,6 +430,33 @@ Java_net_mynero_wallet_model_WalletManager_recoveryWalletJ(JNIEnv *env, jobject return reinterpret_cast(wallet); } +JNIEXPORT jlong JNICALL +Java_net_mynero_wallet_model_WalletManager_recoveryWalletPolyseedJ(JNIEnv *env, jobject instance, + jstring path, jstring password, + jstring mnemonic, jstring offset, + jint networkType) { + const char *_path = env->GetStringUTFChars(path, nullptr); + const char *_password = env->GetStringUTFChars(password, nullptr); + const char *_mnemonic = env->GetStringUTFChars(mnemonic, nullptr); + const char *_offset = env->GetStringUTFChars(offset, nullptr); + Monero::NetworkType _networkType = static_cast(networkType); + + Monero::Wallet *wallet = + Monero::WalletManagerFactory::getWalletManager()->createWalletFromPolyseed( + std::string(_path), + std::string(_password), + _networkType, + std::string(_mnemonic), + std::string(_offset), false); + + env->ReleaseStringUTFChars(path, _path); + env->ReleaseStringUTFChars(password, _password); + env->ReleaseStringUTFChars(mnemonic, _mnemonic); + env->ReleaseStringUTFChars(offset, _offset); + return reinterpret_cast(wallet); +} + + JNIEXPORT jlong JNICALL Java_net_mynero_wallet_model_WalletManager_createWalletFromKeysJ(JNIEnv *env, jobject instance, jstring path, jstring password, @@ -645,11 +707,55 @@ JNIEXPORT jstring JNICALL Java_net_mynero_wallet_model_Wallet_getSeed(JNIEnv *env, jobject instance, jstring seedOffset) { const char *_seedOffset = env->GetStringUTFChars(seedOffset, nullptr); Monero::Wallet *wallet = getHandle(env, instance); - jstring seed = env->NewStringUTF(wallet->seed(std::string(_seedOffset)).c_str()); + + std::string _seed; + std::string seedOffsetStr(_seedOffset); + bool _getPolyseed = wallet->getPolyseed(_seed, seedOffsetStr); + + if (_getPolyseed) { + LOGD("_getPolyseed: true"); + } else { + LOGD("_getPolyseed: false"); + LOGE("wallet->getSeed() %s", wallet->errorString().c_str()); + LOGD("Falling back to normal, boring, seed"); + _seed = wallet->seed(std::string(_seedOffset)); + } + env->ReleaseStringUTFChars(seedOffset, _seedOffset); + + jstring seed = env->NewStringUTF(_seed.c_str()); return seed; } +JNIEXPORT jstring JNICALL +Java_net_mynero_wallet_model_Wallet_getLegacySeed(JNIEnv *env, jobject instance, jstring seedOffset) { + const char *_seedOffset = env->GetStringUTFChars(seedOffset, nullptr); + Monero::Wallet *wallet = getHandle(env, instance); + + std::string _seed; + std::string seedOffsetStr(_seedOffset); + _seed = wallet->seed(std::string(_seedOffset)); + + env->ReleaseStringUTFChars(seedOffset, _seedOffset); + + jstring seed = env->NewStringUTF(_seed.c_str()); + return seed; +} + +JNIEXPORT jboolean JNICALL +Java_net_mynero_wallet_model_Wallet_isPolyseedSupported(JNIEnv *env, jobject instance, jstring seedOffset) { + const char *_seedOffset = env->GetStringUTFChars(seedOffset, nullptr); + Monero::Wallet *wallet = getHandle(env, instance); + + std::string _seed; + std::string seedOffsetStr(_seedOffset); + bool _getPolyseed = wallet->getPolyseed(_seed, seedOffsetStr); + + env->ReleaseStringUTFChars(seedOffset, _seedOffset); + return _getPolyseed; +} + + JNIEXPORT jstring JNICALL Java_net_mynero_wallet_model_Wallet_getSeedLanguage(JNIEnv *env, jobject instance) { Monero::Wallet *wallet = getHandle(env, instance); diff --git a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java index f7a8c33..f0d775a 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java +++ b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingFragment.java @@ -198,6 +198,17 @@ public class OnboardingFragment extends Fragment implements NodeSelectionBottomS @Override public void afterTextChanged(Editable editable) { String text = editable.toString(); + OnboardingViewModel.SeedType seedType = mViewModel.getMnemonicType(text); + if(seedType == OnboardingViewModel.SeedType.LEGACY) { + seedOffsetCheckbox.setVisibility(View.VISIBLE); + walletRestoreHeightEditText.setVisibility(View.VISIBLE); + walletPasswordEditText.setHint(getString(R.string.password_optional)); + } else { + seedOffsetCheckbox.setVisibility(View.GONE); + walletRestoreHeightEditText.setVisibility(View.GONE); + walletPasswordEditText.setHint(getString(R.string.password_non_optional)); + } + if (text.isEmpty()) { createWalletButton.setText(R.string.create_wallet); } else { diff --git a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingViewModel.java b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingViewModel.java index aabd86f..2dcc5d5 100644 --- a/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingViewModel.java +++ b/app/src/main/java/net/mynero/wallet/fragment/onboarding/OnboardingViewModel.java @@ -71,6 +71,7 @@ public class OnboardingViewModel extends ViewModel { String offset = useOffset ? walletPassword : ""; if (!walletPassword.isEmpty()) { if(!walletPassword.equals(confirmedPassword)) { + _enableCreateButton.setValue(true); mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, application.getString(R.string.invalid_confirmed_password), Toast.LENGTH_SHORT).show()); return; } @@ -84,11 +85,21 @@ public class OnboardingViewModel extends ViewModel { } if (walletSeed.isEmpty()) { - Wallet tmpWallet = createTempWallet(mainActivity.getApplicationInfo().dataDir); //we do this to get seed, then recover wallet so we can use seed offset - wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, tmpWallet.getSeed(""), offset, restoreHeight); + if(offset.isEmpty()) { + mainActivity.runOnUiThread(() -> { + _enableCreateButton.setValue(true); + Toast.makeText(mainActivity, application.getString(R.string.invalid_empty_passphrase), Toast.LENGTH_SHORT).show(); + }); + return; + } else { + wallet = WalletManager.getInstance().createWalletPolyseed(walletFile, walletPassword, offset, Constants.MNEMONIC_LANGUAGE); + } } else { - if (!checkMnemonic(walletSeed)) { - mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, application.getString(R.string.invalid_mnemonic_code), Toast.LENGTH_SHORT).show()); + if (getMnemonicType(walletSeed) == SeedType.UNKNOWN) { + mainActivity.runOnUiThread(() -> { + _enableCreateButton.setValue(true); + Toast.makeText(mainActivity, application.getString(R.string.invalid_mnemonic_code), Toast.LENGTH_SHORT).show(); + }); return; } if (!restoreHeightText.isEmpty()) { @@ -99,7 +110,7 @@ public class OnboardingViewModel extends ViewModel { Wallet.Status walletStatus = wallet.getStatus(); wallet.close(); boolean ok = walletStatus.isOk(); - walletFile.delete(); // cache is broken for some reason when recovering wallets. delete the file here. this happens in monerujo too. + //walletFile.delete(); // cache is broken for some reason when recovering wallets. delete the file here. this happens in monerujo too. if (ok) { ((MainActivity)mainActivity).init(walletFile, walletPassword); @@ -119,12 +130,20 @@ public class OnboardingViewModel extends ViewModel { return RestoreHeight.getInstance().getHeight(restoreDate.getTime()); } - private Wallet createTempWallet(String dir) { - File tmpWalletFile = new File(dir, Constants.WALLET_NAME + "_tmp"); - return WalletManager.getInstance().createWallet(tmpWalletFile, "", Constants.MNEMONIC_LANGUAGE, 0); + public SeedType getMnemonicType(String seed) { + String[] words = seed.split("\\s"); + if(words.length == 16) { + return SeedType.POLYSEED; + } else if (words.length == 25){ + return SeedType.LEGACY; + } else { + return SeedType.UNKNOWN; + } } - private boolean checkMnemonic(String seed) { - return (seed.split("\\s").length == 25); + public enum SeedType { + LEGACY, + POLYSEED, + UNKNOWN } } \ No newline at end of file diff --git a/app/src/main/java/net/mynero/wallet/model/Wallet.java b/app/src/main/java/net/mynero/wallet/model/Wallet.java index 446cc4e..6ec41d6 100644 --- a/app/src/main/java/net/mynero/wallet/model/Wallet.java +++ b/app/src/main/java/net/mynero/wallet/model/Wallet.java @@ -16,6 +16,7 @@ package net.mynero.wallet.model; +import android.util.Log; import android.util.Pair; import androidx.annotation.NonNull; @@ -94,6 +95,10 @@ public class Wallet { public native String getSeed(String offset); + public native String getLegacySeed(String offset); + + public native boolean isPolyseedSupported(String offset); + public native String getSeedLanguage(); public native void setSeedLanguage(String language); @@ -189,11 +194,43 @@ public class Wallet { // virtual std::string keysFilename() const = 0; public boolean init(long upper_transaction_size_limit) { - return initJ(WalletManager.getInstance().getDaemonAddress(), upper_transaction_size_limit, - WalletManager.getInstance().getDaemonUsername(), - WalletManager.getInstance().getDaemonPassword(), WalletManager.getInstance().getProxy()); + String daemon_address = WalletManager.getInstance().getDaemonAddress(); + String daemon_username = WalletManager.getInstance().getDaemonUsername(); + String daemon_password = WalletManager.getInstance().getDaemonPassword(); + String proxy_address = WalletManager.getInstance().getProxy(); + Log.d("Wallet.java", "init("); + if (daemon_address != null) { + Log.d("Wallet.java", daemon_address.toString()); + } else { + Log.d("Wallet.java", "daemon_address == null"); + daemon_address = ""; + } + Log.d("Wallet.java", "upper_transaction_size_limit = 0 (probably)"); + if (daemon_username != null) { + Log.d("Wallet.java", daemon_username.toString()); + } else { + Log.d("Wallet.java", "daemon_username == null"); + daemon_username = ""; + } + if (daemon_password != null) { + Log.d("Wallet.java", daemon_password.toString()); + } else { + Log.d("Wallet.java", "daemon_password == null"); + daemon_password = ""; + } + if (proxy_address != null) { + Log.d("Wallet.java", proxy_address.toString()); + } else { + Log.d("Wallet.java", "proxy_address == null"); + proxy_address = ""; + } + Log.d("Wallet.java", ");"); + return initJ(daemon_address, upper_transaction_size_limit, + daemon_username, daemon_password, + proxy_address); } + private native boolean initJ(String daemon_address, long upper_transaction_size_limit, String daemon_username, String daemon_password, String proxy); diff --git a/app/src/main/java/net/mynero/wallet/model/WalletManager.java b/app/src/main/java/net/mynero/wallet/model/WalletManager.java index a7d0788..c58d0ea 100644 --- a/app/src/main/java/net/mynero/wallet/model/WalletManager.java +++ b/app/src/main/java/net/mynero/wallet/model/WalletManager.java @@ -136,6 +136,18 @@ public class WalletManager { private native long createWalletJ(String path, String password, String language, int networkType); + public Wallet createWalletPolyseed(File aFile, String password, String passphrase, String language) { + long walletHandle = createWalletPolyseedJ(aFile.getAbsolutePath(), password, passphrase, language, getNetworkType().getValue()); + Wallet wallet = new Wallet(walletHandle); + manageWallet(wallet); + if (wallet.getStatus().isOk()) { + wallet.setPassword(password); // this rewrites the keys file (which contains the restore height) + } else + Timber.e(wallet.getStatus().toString()); + return wallet; + } + private native long createWalletPolyseedJ(String path, String password, String passphrase, String language, int networkType); + public Wallet openAccount(String path, int accountIndex, String password) { long walletHandle = openWalletJ(path, password, getNetworkType().getValue()); Wallet wallet = new Wallet(walletHandle, accountIndex); @@ -169,6 +181,20 @@ public class WalletManager { String mnemonic, String offset, int networkType, long restoreHeight); + public Wallet recoveryWalletPolyseed(File aFile, String password, + String mnemonic, String offset) { + long walletHandle = recoveryWalletPolyseedJ(aFile.getAbsolutePath(), password, + mnemonic, offset, + getNetworkType().getValue()); + Wallet wallet = new Wallet(walletHandle); + manageWallet(wallet); + return wallet; + } + + private native long recoveryWalletPolyseedJ(String path, String password, + String mnemonic, String offset, + int networkType); + public Wallet createWalletWithKeys(File aFile, String password, String language, long restoreHeight, String addressString, String viewKeyString, String spendKeyString) { long walletHandle = createWalletFromKeysJ(aFile.getAbsolutePath(), password, diff --git a/app/src/main/res/layout/fragment_onboarding.xml b/app/src/main/res/layout/fragment_onboarding.xml index ee7dfe3..871d13d 100644 --- a/app/src/main/res/layout/fragment_onboarding.xml +++ b/app/src/main/res/layout/fragment_onboarding.xml @@ -38,7 +38,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:background="@drawable/edittext_bg" - android:hint="@string/password_optional" + android:hint="@string/password_non_optional" android:inputType="textPassword" android:minHeight="48dp" app:layout_constraintBottom_toTopOf="@id/wallet_password_confirm_edittext" @@ -56,21 +56,12 @@ android:hint="@string/password_confirm" android:inputType="textPassword" android:visibility="gone" - app:layout_constraintBottom_toTopOf="@id/seed_offset_checkbox" + app:layout_constraintBottom_toTopOf="@id/advanced_settings_dropdown_textview" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/wallet_password_edittext" tools:visibility="gone" /> - - + app:layout_constraintTop_toBottomOf="@id/wallet_password_confirm_edittext" /> @@ -148,7 +141,6 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginBottom="16dp" - android:layout_marginTop="32dp" android:background="@drawable/edittext_bg" android:hint="@string/recovery_phrase_optional" android:minHeight="48dp" @@ -165,11 +157,23 @@ android:hint="@string/restore_height_optional" android:inputType="number" android:minHeight="48dp" - app:layout_constraintBottom_toTopOf="@id/tor_onboarding_switch" + android:visibility="gone" + app:layout_constraintBottom_toTopOf="@id/seed_offset_checkbox" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/wallet_seed_edittext" /> + + + app:layout_constraintTop_toBottomOf="@id/seed_offset_checkbox" /> Error creating: %1$s Create wallet Invalid mnemonic + Please enter a password Passwords do not match Copied to clipboard Street mode (hide balances) @@ -50,6 +51,7 @@ Recovery phrase (optional) Restore height (optional) Password (optional) + Enter a password Confirm password Password Label diff --git a/external-libs/android32.Dockerfile b/external-libs/android32.Dockerfile index 3173e2d..6209139 100644 --- a/external-libs/android32.Dockerfile +++ b/external-libs/android32.Dockerfile @@ -158,6 +158,27 @@ RUN set -x \ && make -j${NPROC} \ && make install +# polyseed +RUN git clone https://github.com/tevador/polyseed.git +RUN set -x \ + && cd polyseed \ + && git reset --hard b7c35bb3c6b91e481ecb04fc235eaff69c507fa1 \ + && CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} . \ + && make \ + && make install + +# utf8proc +RUN git clone https://github.com/JuliaStrings/utf8proc -b v2.8.0 +RUN set -x \ + && cd utf8proc \ + && git reset --hard 1cb28a66ca79a0845e99433fd1056257456cef8b \ + && mkdir build \ + && cd build \ + && rm -rf ../CMakeCache.txt ../CMakeFiles/ \ + && CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} .. \ + && make \ + && make install + COPY . /src RUN set -x \ && cd /src \ diff --git a/external-libs/android32_x86.Dockerfile b/external-libs/android32_x86.Dockerfile index 83bd9a0..b9c5243 100644 --- a/external-libs/android32_x86.Dockerfile +++ b/external-libs/android32_x86.Dockerfile @@ -158,6 +158,27 @@ RUN set -x \ && make -j${NPROC} \ && make install +# polyseed +RUN git clone https://github.com/tevador/polyseed.git +RUN set -x \ + && cd polyseed \ + && git reset --hard b7c35bb3c6b91e481ecb04fc235eaff69c507fa1 \ + && CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} . \ + && make \ + && make install + +# utf8proc +RUN git clone https://github.com/JuliaStrings/utf8proc -b v2.8.0 +RUN set -x \ + && cd utf8proc \ + && git reset --hard 1cb28a66ca79a0845e99433fd1056257456cef8b \ + && mkdir build \ + && cd build \ + && rm -rf ../CMakeCache.txt ../CMakeFiles/ \ + && CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} .. \ + && make \ + && make install + COPY . /src RUN set -x \ && cd /src \ diff --git a/external-libs/android64.Dockerfile b/external-libs/android64.Dockerfile index bd11bef..37cffb4 100644 --- a/external-libs/android64.Dockerfile +++ b/external-libs/android64.Dockerfile @@ -158,6 +158,27 @@ RUN set -x \ && make -j${NPROC} \ && make install +# polyseed +RUN git clone https://github.com/tevador/polyseed.git +RUN set -x \ + && cd polyseed \ + && git reset --hard b7c35bb3c6b91e481ecb04fc235eaff69c507fa1 \ + && CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} . \ + && make \ + && make install + +# utf8proc +RUN git clone https://github.com/JuliaStrings/utf8proc -b v2.8.0 +RUN set -x \ + && cd utf8proc \ + && git reset --hard 1cb28a66ca79a0845e99433fd1056257456cef8b \ + && mkdir build \ + && cd build \ + && rm -rf ../CMakeCache.txt ../CMakeFiles/ \ + && CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} .. \ + && make \ + && make install + COPY . /src RUN set -x \ && cd /src \ diff --git a/external-libs/android64_x86.Dockerfile b/external-libs/android64_x86.Dockerfile index 00ced95..84e32a5 100644 --- a/external-libs/android64_x86.Dockerfile +++ b/external-libs/android64_x86.Dockerfile @@ -158,6 +158,27 @@ RUN set -x \ && make -j${NPROC} \ && make install +# polyseed +RUN git clone https://github.com/tevador/polyseed.git +RUN set -x \ + && cd polyseed \ + && git reset --hard b7c35bb3c6b91e481ecb04fc235eaff69c507fa1 \ + && CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} . \ + && make \ + && make install + +# utf8proc +RUN git clone https://github.com/JuliaStrings/utf8proc -b v2.8.0 +RUN set -x \ + && cd utf8proc \ + && git reset --hard 1cb28a66ca79a0845e99433fd1056257456cef8b \ + && mkdir build \ + && cd build \ + && rm -rf ../CMakeCache.txt ../CMakeFiles/ \ + && CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} .. \ + && make \ + && make install + COPY . /src RUN set -x \ && cd /src \ diff --git a/external-libs/include/wallet2_api.h b/external-libs/include/wallet2_api.h index 5df4ad7..942b17d 100644 --- a/external-libs/include/wallet2_api.h +++ b/external-libs/include/wallet2_api.h @@ -745,6 +745,10 @@ struct Wallet static void warning(const std::string &category, const std::string &str); static void error(const std::string &category, const std::string &str); + virtual bool getPolyseed(std::string &seed, std::string &passphrase) const = 0; + static bool createPolyseed(std::string &seed_words, std::string &err, const std::string &language = "English"); + static std::vector> getPolyseedLanguages(); + /** * @brief StartRefresh - Start/resume refresh thread (refresh every 10 seconds) */ @@ -1304,6 +1308,27 @@ struct WalletManager uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) = 0; + /*! + * \brief creates a wallet from a polyseed mnemonic phrase + * \param path Name of the wallet file to be created + * \param password Password of wallet file + * \param nettype Network type + * \param mnemonic Polyseed mnemonic + * \param passphrase Optional seed offset passphrase + * \param newWallet Whether it is a new wallet + * \param restoreHeight Override the embedded restore height + * \param kdf_rounds Number of rounds for key derivation function + * @return + */ + virtual Wallet * createWalletFromPolyseed(const std::string &path, + const std::string &password, + NetworkType nettype, + const std::string &mnemonic, + const std::string &passphrase = "", + bool newWallet = true, + uint64_t restore_height = 0, + uint64_t kdf_rounds = 1) = 0; + /*! * \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted * \param wallet previously opened / created wallet instance