Add seed offset support

This commit is contained in:
pokkst 2022-11-05 11:23:30 -05:00
parent 39bb06c833
commit b66c81cedc
No known key found for this signature in database
GPG key ID: 90C2ED85E67A50FF
7 changed files with 57 additions and 14 deletions

View file

@ -15,9 +15,12 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import net.mynero.wallet.R; import net.mynero.wallet.R;
import net.mynero.wallet.model.Wallet; import net.mynero.wallet.model.Wallet;
import net.mynero.wallet.model.WalletManager; import net.mynero.wallet.model.WalletManager;
import net.mynero.wallet.service.PrefService;
import net.mynero.wallet.util.Constants;
import net.mynero.wallet.util.Helper; import net.mynero.wallet.util.Helper;
public class WalletKeysBottomSheetDialog extends BottomSheetDialogFragment { public class WalletKeysBottomSheetDialog extends BottomSheetDialogFragment {
public String password = "";
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -34,6 +37,11 @@ public class WalletKeysBottomSheetDialog extends BottomSheetDialogFragment {
Wallet wallet = WalletManager.getInstance().getWallet(); Wallet wallet = WalletManager.getInstance().getWallet();
String seed = wallet.getSeed(""); String seed = wallet.getSeed("");
boolean usesOffset = PrefService.getInstance().getBoolean(Constants.PREF_USES_OFFSET, false);
if(usesOffset) {
seed = wallet.getSeed(password);
view.findViewById(R.id.wallet_seed_offset_textview).setVisibility(View.VISIBLE);
}
String privateViewKey = wallet.getSecretViewKey(); String privateViewKey = wallet.getSecretViewKey();
informationTextView.setText(seed); informationTextView.setText(seed);

View file

@ -8,6 +8,8 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
@ -23,18 +25,19 @@ import androidx.lifecycle.ViewModelProvider;
import net.mynero.wallet.MainActivity; import net.mynero.wallet.MainActivity;
import net.mynero.wallet.MoneroApplication; import net.mynero.wallet.MoneroApplication;
import net.mynero.wallet.R; import net.mynero.wallet.R;
import net.mynero.wallet.data.DefaultNodes;
import net.mynero.wallet.model.Wallet; import net.mynero.wallet.model.Wallet;
import net.mynero.wallet.model.WalletManager; import net.mynero.wallet.model.WalletManager;
import net.mynero.wallet.service.PrefService; import net.mynero.wallet.service.PrefService;
import net.mynero.wallet.util.Constants; import net.mynero.wallet.util.Constants;
import net.mynero.wallet.util.RestoreHeight; import net.mynero.wallet.util.RestoreHeight;
import org.json.JSONObject;
import java.io.File; import java.io.File;
import java.util.Calendar; import java.util.Calendar;
public class OnboardingFragment extends Fragment { public class OnboardingFragment extends Fragment {
private boolean useOffset = true;
private OnboardingViewModel mViewModel; private OnboardingViewModel mViewModel;
TextWatcher proxyAddressListener = new TextWatcher() { TextWatcher proxyAddressListener = new TextWatcher() {
@Override @Override
@ -91,12 +94,16 @@ public class OnboardingFragment extends Fragment {
ImageView moreOptionsChevronImageView = view.findViewById(R.id.advanced_settings_chevron_imageview); ImageView moreOptionsChevronImageView = view.findViewById(R.id.advanced_settings_chevron_imageview);
SwitchCompat torSwitch = view.findViewById(R.id.tor_onboarding_switch); SwitchCompat torSwitch = view.findViewById(R.id.tor_onboarding_switch);
ConstraintLayout proxySettingsLayout = view.findViewById(R.id.wallet_proxy_settings_layout); ConstraintLayout proxySettingsLayout = view.findViewById(R.id.wallet_proxy_settings_layout);
CheckBox seedOffsetCheckbox = view.findViewById(R.id.seed_offset_checkbox);
walletProxyAddressEditText = view.findViewById(R.id.wallet_proxy_address_edittext); walletProxyAddressEditText = view.findViewById(R.id.wallet_proxy_address_edittext);
walletProxyPortEditText = view.findViewById(R.id.wallet_proxy_port_edittext); walletProxyPortEditText = view.findViewById(R.id.wallet_proxy_port_edittext);
seedOffsetCheckbox.setChecked(useOffset);
moreOptionsDropdownTextView.setOnClickListener(view12 -> mViewModel.onMoreOptionsClicked()); moreOptionsDropdownTextView.setOnClickListener(view12 -> mViewModel.onMoreOptionsClicked());
moreOptionsChevronImageView.setOnClickListener(view12 -> mViewModel.onMoreOptionsClicked()); moreOptionsChevronImageView.setOnClickListener(view12 -> mViewModel.onMoreOptionsClicked());
seedOffsetCheckbox.setOnCheckedChangeListener((compoundButton, b) -> useOffset = b);
createWalletButton.setOnClickListener(view1 -> { createWalletButton.setOnClickListener(view1 -> {
prepareDefaultNode(); prepareDefaultNode();
((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> { ((MoneroApplication)getActivity().getApplication()).getExecutor().execute(() -> {
@ -165,17 +172,18 @@ public class OnboardingFragment extends Fragment {
} }
private void createOrImportWallet(String walletPassword, String walletSeed, String restoreHeightText) { private void createOrImportWallet(String walletPassword, String walletSeed, String restoreHeightText) {
String offset = useOffset ? walletPassword : "";
MainActivity mainActivity = (MainActivity) getActivity(); MainActivity mainActivity = (MainActivity) getActivity();
if (mainActivity != null) { if (mainActivity != null) {
if (!walletPassword.isEmpty()) { if (!walletPassword.isEmpty()) {
PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_PASSWORD, true).apply(); PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_PASSWORD, true).apply();
} }
long restoreHeight = -1; long restoreHeight = getNewRestoreHeight();
File walletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME); File walletFile = new File(mainActivity.getApplicationInfo().dataDir, Constants.WALLET_NAME);
Wallet wallet = null; Wallet wallet = null;
if (walletSeed.isEmpty()) { 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 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(""), "", getNewRestoreHeight()); wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, tmpWallet.getSeed(""), offset, restoreHeight);
} else { } else {
if (!checkMnemonic(walletSeed)) { if (!checkMnemonic(walletSeed)) {
Toast.makeText(mainActivity, getString(R.string.invalid_mnemonic_code), Toast.LENGTH_SHORT).show(); Toast.makeText(mainActivity, getString(R.string.invalid_mnemonic_code), Toast.LENGTH_SHORT).show();
@ -184,7 +192,10 @@ public class OnboardingFragment extends Fragment {
if (!restoreHeightText.isEmpty()) { if (!restoreHeightText.isEmpty()) {
restoreHeight = Long.parseLong(restoreHeightText); restoreHeight = Long.parseLong(restoreHeightText);
} }
wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, walletSeed, "", restoreHeight); if(!offset.isEmpty()) {
PrefService.getInstance().edit().putBoolean(Constants.PREF_USES_OFFSET, true).apply();
}
wallet = WalletManager.getInstance().recoveryWallet(walletFile, walletPassword, walletSeed, offset, restoreHeight);
} }
Wallet.Status walletStatus = wallet.getStatus(); Wallet.Status walletStatus = wallet.getStatus();
wallet.close(); wallet.close();

View file

@ -156,7 +156,7 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia
passwordDialog.listener = this; passwordDialog.listener = this;
passwordDialog.show(getActivity().getSupportFragmentManager(), "password_dialog"); passwordDialog.show(getActivity().getSupportFragmentManager(), "password_dialog");
} else { } else {
displaySeedDialog(); displaySeedDialog("");
} }
}); });
@ -183,14 +183,15 @@ public class SettingsFragment extends Fragment implements PasswordBottomSheetDia
}); });
} }
private void displaySeedDialog() { private void displaySeedDialog(String password) {
WalletKeysBottomSheetDialog informationDialog = new WalletKeysBottomSheetDialog(); WalletKeysBottomSheetDialog informationDialog = new WalletKeysBottomSheetDialog();
informationDialog.password = password;
informationDialog.show(getActivity().getSupportFragmentManager(), "information_seed_dialog"); informationDialog.show(getActivity().getSupportFragmentManager(), "information_seed_dialog");
} }
@Override @Override
public void onPasswordSuccess(String password) { public void onPasswordSuccess(String password) {
displaySeedDialog(); displaySeedDialog(password);
} }
@Override @Override

View file

@ -9,6 +9,7 @@ public class Constants {
public static final String PREF_PROXY = "pref_proxy"; public static final String PREF_PROXY = "pref_proxy";
public static final String PREF_NODE_2 = "pref_node_2"; public static final String PREF_NODE_2 = "pref_node_2";
public static final String PREF_CUSTOM_NODES = "pref_custom_nodes"; public static final String PREF_CUSTOM_NODES = "pref_custom_nodes";
public static final String PREF_USES_OFFSET = "pref_uses_offset";
public static final String URI_PREFIX = "monero:"; public static final String URI_PREFIX = "monero:";
public static final String URI_ARG_AMOUNT = "tx_amount"; public static final String URI_ARG_AMOUNT = "tx_amount";

View file

@ -34,6 +34,14 @@
app:layout_constraintTop_toBottomOf="@id/create_wallet_textview" app:layout_constraintTop_toBottomOf="@id/create_wallet_textview"
tools:visibility="visible" /> tools:visibility="visible" />
<CheckBox
android:id="@+id/seed_offset_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/use_password_as_seed_offset"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_password_edittext"/>
<TextView <TextView
android:id="@+id/tor_onboarding_switch_label" android:id="@+id/tor_onboarding_switch_label"
android:layout_width="0dp" android:layout_width="0dp"
@ -49,10 +57,9 @@
android:id="@+id/tor_onboarding_switch" android:id="@+id/tor_onboarding_switch"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:minHeight="48dp" android:minHeight="48dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_password_edittext" /> app:layout_constraintTop_toBottomOf="@id/seed_offset_checkbox" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/wallet_proxy_settings_layout" android:id="@+id/wallet_proxy_settings_layout"

View file

@ -50,12 +50,25 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_seed_label_textview" /> app:layout_constraintTop_toBottomOf="@id/wallet_seed_label_textview" />
<TextView
android:id="@+id/wallet_seed_offset_textview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="11sp"
android:textColor="#f80"
android:visibility="gone"
android:text="@string/wallet_seed_offset_desc"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/information_textview" />
<TextView <TextView
android:id="@+id/information_textview" android:id="@+id/information_textview"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:textSize="14sp" android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_seed_desc_textview" app:layout_constraintTop_toBottomOf="@id/wallet_seed_desc_textview"
@ -71,7 +84,7 @@
android:text="@string/wallet_viewkey_label" android:text="@string/wallet_viewkey_label"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/information_textview" /> app:layout_constraintTop_toBottomOf="@id/wallet_seed_offset_textview" />
<TextView <TextView
android:id="@+id/wallet_viewkey_desc_textview" android:id="@+id/wallet_viewkey_desc_textview"
@ -90,7 +103,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:textSize="14sp" android:textSize="16sp"
app:layout_constraintEnd_toStartOf="@id/copy_viewkey_imagebutton" app:layout_constraintEnd_toStartOf="@id/copy_viewkey_imagebutton"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/copy_viewkey_imagebutton" app:layout_constraintTop_toTopOf="@id/copy_viewkey_imagebutton"
@ -125,7 +138,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:textSize="14sp" android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/wallet_restore_height_label_textview" app:layout_constraintTop_toBottomOf="@id/wallet_restore_height_label_textview"

View file

@ -108,8 +108,10 @@
<string name="edit_node">Edit Node</string> <string name="edit_node">Edit Node</string>
<string name="wallet_seed_label">Recovery phrase</string> <string name="wallet_seed_label">Recovery phrase</string>
<string name="wallet_seed_desc">Anyone with your recovery phrase can spend ALL coins in this wallet!</string> <string name="wallet_seed_desc">Anyone with your recovery phrase can spend ALL coins in this wallet!</string>
<string name="wallet_seed_offset_desc">Your wallet seed offset is the password you use to open the wallet. It will not be displayed here, but it is needed to fully restore this wallet.</string>
<string name="wallet_viewkey_label">Private view-key</string> <string name="wallet_viewkey_label">Private view-key</string>
<string name="wallet_viewkey_desc">Anyone with your private view-key can see all incoming transactions!</string> <string name="wallet_viewkey_desc">Anyone with your private view-key can see all incoming transactions!</string>
<string name="wallet_restore_height_label">Restore height</string> <string name="wallet_restore_height_label">Restore height</string>
<string name="block_height">Block Height</string> <string name="block_height">Block Height</string>
<string name="use_password_as_seed_offset">Use password as seed offset</string>
</resources> </resources>