Merge pull request #10032 from brave/import-legacy-brave-mnemonic

Import legacy brave mnemonic
This commit is contained in:
Anthony Tseng
2021-09-13 11:16:04 -07:00
committed by GitHub
13 changed files with 225 additions and 70 deletions
@@ -84,7 +84,7 @@ public class RestoreWalletFragment extends CryptoOnboardingFragment {
KeyringController keyringController = getKeyringController();
if (keyringController != null) {
keyringController.restoreWallet(recoveryPhraseText.getText().toString().trim(),
passwordEdittext.getText().toString().trim(), result -> {
passwordEdittext.getText().toString().trim(), false, result -> {
if (result) {
Utils.hideKeyboard(getActivity());
onNextPage.gotoNextPage(true);
@@ -274,10 +274,10 @@ TEST_F(KeyringControllerUnitTest, CreateEncryptorForKeyring) {
TEST_F(KeyringControllerUnitTest, CreateDefaultKeyringInternal) {
KeyringController controller(GetPrefs());
// encryptor is nullptr
ASSERT_FALSE(controller.CreateDefaultKeyringInternal(kMnemonic1));
ASSERT_FALSE(controller.CreateDefaultKeyringInternal(kMnemonic1, false));
EXPECT_TRUE(controller.CreateEncryptorForKeyring("brave", "default"));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1, false));
controller.default_keyring_->AddAccounts(1);
EXPECT_EQ(controller.default_keyring_->GetAddress(0),
"0xf81229FE54D8a20fBc1e1e2a3451D1c7489437Db");
@@ -291,7 +291,7 @@ TEST_F(KeyringControllerUnitTest, CreateDefaultKeyringInternal) {
encrypted_mnemonic1);
// default keyring will be overwritten
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic2));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic2, false));
controller.default_keyring_->AddAccounts(1);
EXPECT_EQ(controller.default_keyring_->GetAddress(0),
"0xf83C3cBfF68086F276DD4f87A82DF73B57b28820");
@@ -349,7 +349,8 @@ TEST_F(KeyringControllerUnitTest, RestoreDefaultKeyring) {
const std::string mnemonic = controller.GetMnemonicForDefaultKeyringImpl();
// Restore with same mnemonic and same password
EXPECT_NE(controller.RestoreDefaultKeyring(mnemonic, "brave"), nullptr);
EXPECT_NE(controller.RestoreDefaultKeyring(mnemonic, "brave", false),
nullptr);
EXPECT_EQ(GetStringPrefForKeyring(kEncryptedMnemonic, "default"),
encrypted_mnemonic);
EXPECT_EQ(GetStringPrefForKeyring(kPasswordEncryptorSalt, "default"), salt);
@@ -357,7 +358,8 @@ TEST_F(KeyringControllerUnitTest, RestoreDefaultKeyring) {
EXPECT_EQ(controller.default_keyring_->GetAccountsNumber(), 1u);
// Restore with same mnemonic but different password
EXPECT_NE(controller.RestoreDefaultKeyring(mnemonic, "brave377"), nullptr);
EXPECT_NE(controller.RestoreDefaultKeyring(mnemonic, "brave377", false),
nullptr);
EXPECT_NE(GetStringPrefForKeyring(kEncryptedMnemonic, "default"),
encrypted_mnemonic);
EXPECT_NE(GetStringPrefForKeyring(kPasswordEncryptorSalt, "default"), salt);
@@ -371,7 +373,7 @@ TEST_F(KeyringControllerUnitTest, RestoreDefaultKeyring) {
nonce = GetStringPrefForKeyring(kPasswordEncryptorNonce, "default");
// Restore with invalid mnemonic but same password
EXPECT_EQ(controller.RestoreDefaultKeyring("", "brave"), nullptr);
EXPECT_EQ(controller.RestoreDefaultKeyring("", "brave", false), nullptr);
// Keyring prefs won't be cleared
EXPECT_EQ(GetStringPrefForKeyring(kEncryptedMnemonic, "default"),
encrypted_mnemonic);
@@ -380,7 +382,7 @@ TEST_F(KeyringControllerUnitTest, RestoreDefaultKeyring) {
EXPECT_EQ(controller.default_keyring_->GetAccountsNumber(), 0u);
// Restore with same mnemonic but empty password
EXPECT_EQ(controller.RestoreDefaultKeyring(mnemonic, ""), nullptr);
EXPECT_EQ(controller.RestoreDefaultKeyring(mnemonic, "", false), nullptr);
// Keyring prefs won't be cleared
EXPECT_EQ(GetStringPrefForKeyring(kEncryptedMnemonic, "default"),
encrypted_mnemonic);
@@ -390,7 +392,8 @@ TEST_F(KeyringControllerUnitTest, RestoreDefaultKeyring) {
// default keyring will be overwritten by new seed which will be encrypted by
// new key even though the passphrase is same.
EXPECT_NE(controller.RestoreDefaultKeyring(kMnemonic1, "brave"), nullptr);
EXPECT_NE(controller.RestoreDefaultKeyring(kMnemonic1, "brave", false),
nullptr);
EXPECT_NE(GetStringPrefForKeyring(kEncryptedMnemonic, "default"),
encrypted_mnemonic);
// salt is regenerated and account num is cleared
@@ -461,7 +464,7 @@ TEST_F(KeyringControllerUnitTest, GetMnemonicForDefaultKeyring) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(string_value().empty());
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1, false));
controller.GetMnemonicForDefaultKeyring(base::BindOnce(
&KeyringControllerUnitTest::GetStringCallback, base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -655,7 +658,7 @@ TEST_F(KeyringControllerUnitTest, BackupComplete) {
TEST_F(KeyringControllerUnitTest, AccountMetasForKeyring) {
KeyringController controller(GetPrefs());
EXPECT_TRUE(controller.CreateEncryptorForKeyring("brave", "default"));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1, false));
controller.default_keyring_->AddAccounts(2);
const std::string address1 = controller.default_keyring_->GetAddress(0);
const std::string name1 = "Account1";
@@ -718,21 +721,27 @@ TEST_F(KeyringControllerUnitTest, CreateAndRestoreWallet) {
EXPECT_EQ(account_infos[0]->name, "Account 1");
controller.Reset();
callback_called = false;
controller.RestoreWallet(mnemonic_to_be_restored, "brave1",
base::BindLambdaForTesting([&](bool success) {
EXPECT_TRUE(success);
callback_called = true;
}));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback_called);
{
std::vector<mojom::AccountInfoPtr> account_infos =
controller.GetAccountInfosForKeyring("default");
EXPECT_EQ(account_infos.size(), 1u);
EXPECT_EQ(account_infos[0]->address, address0);
EXPECT_EQ(account_infos[0]->name, "Account 1");
}
auto verify_restore_wallet = base::BindLambdaForTesting(
[&mnemonic_to_be_restored, &controller, &address0]() {
bool callback_called = false;
controller.RestoreWallet(mnemonic_to_be_restored, "brave1", false,
base::BindLambdaForTesting([&](bool success) {
EXPECT_TRUE(success);
callback_called = true;
}));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback_called);
{
std::vector<mojom::AccountInfoPtr> account_infos =
controller.GetAccountInfosForKeyring("default");
EXPECT_EQ(account_infos.size(), 1u);
EXPECT_EQ(account_infos[0]->address, address0);
EXPECT_EQ(account_infos[0]->name, "Account 1");
}
});
verify_restore_wallet.Run();
// Restore twice consecutively should succeed and have only one account
verify_restore_wallet.Run();
}
TEST_F(KeyringControllerUnitTest, AddAccount) {
@@ -1089,7 +1098,7 @@ TEST_F(KeyringControllerUnitTest, ImportedAccountFromJson) {
TEST_F(KeyringControllerUnitTest, GetPrivateKeyForDefaultKeyringAccount) {
KeyringController controller(GetPrefs());
EXPECT_TRUE(controller.CreateEncryptorForKeyring("brave", "default"));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1, false));
bool callback_called = false;
controller.GetPrivateKeyForDefaultKeyringAccount(
@@ -1158,7 +1167,7 @@ TEST_F(KeyringControllerUnitTest, SetDefaultKeyringDerivedAccountName) {
EXPECT_TRUE(callback_called);
EXPECT_TRUE(controller.CreateEncryptorForKeyring("brave", "default"));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1));
ASSERT_TRUE(controller.CreateDefaultKeyringInternal(kMnemonic1, false));
controller.default_keyring_->AddAccounts(2);
const std::string address1 = controller.default_keyring_->GetAddress(0);
const std::string name1 = "Account1";
@@ -1341,4 +1350,52 @@ TEST_F(KeyringControllerUnitTest, SetDefaultKeyringImportedAccountName) {
EXPECT_TRUE(callback_called);
}
TEST_F(KeyringControllerUnitTest, RestoreLegacyBraveWallet) {
const char* mnemonic24 =
"cushion pitch impact album daring marine much annual budget social "
"clarify balance rose almost area busy among bring hidden bind later "
"capable pulp laundry";
const char* mnemonic12 =
"drip caution abandon festival order clown oven regular absorb evidence "
"crew where";
KeyringController controller(GetPrefs());
auto verify_restore_wallet = base::BindLambdaForTesting(
[&controller](const char* mnemonic, const char* address, bool is_legacy,
bool expect_result) {
bool callback_called = false;
controller.RestoreWallet(mnemonic, "brave1", is_legacy,
base::BindLambdaForTesting([&](bool success) {
EXPECT_EQ(success, expect_result);
callback_called = true;
}));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback_called);
if (expect_result) {
std::vector<mojom::AccountInfoPtr> account_infos =
controller.GetAccountInfosForKeyring("default");
ASSERT_EQ(account_infos.size(), 1u);
EXPECT_EQ(account_infos[0]->address, address);
EXPECT_EQ(account_infos[0]->name, "Account 1");
// Test lock & unlock to check if it read the right
// legacy_brave_wallet pref so it will use the right seed
controller.Lock();
controller.Unlock("brave1", base::DoNothing::Once<bool>());
base::RunLoop().RunUntilIdle();
account_infos.clear();
account_infos = controller.GetAccountInfosForKeyring("default");
ASSERT_EQ(account_infos.size(), 1u);
EXPECT_EQ(account_infos[0]->address, address);
}
});
verify_restore_wallet.Run(
mnemonic24, "0xea3C17c81E3baC3472d163b2c8b12ddDAa027874", true, true);
verify_restore_wallet.Run(
mnemonic24, "0xe026eBd81C1A64807F9Cbf21d89a67211eF48717", false, true);
// brave legacy menmonic can only be 24 words
verify_restore_wallet.Run(mnemonic12, "", true, false);
verify_restore_wallet.Run(
mnemonic12, "0x084DCb94038af1715963F149079cE011C4B22961", false, true);
}
} // namespace brave_wallet
@@ -51,6 +51,15 @@ std::string GenerateMnemonicInternal(uint8_t* entropy, size_t size) {
return result;
}
bool IsValidEntropySize(size_t entropy_size) {
// entropy size should be 128, 160, 192, 224, 256 bits
if (entropy_size < 16 || entropy_size > 32 || entropy_size % 4 != 0) {
LOG(ERROR) << __func__ << ": Entropy should be 16, 20, 24, 28, 32 bytes";
return false;
}
return true;
}
std::string GetInfuraProjectID() {
std::string project_id(BRAVE_INFURA_PROJECT_ID);
std::unique_ptr<base::Environment> env(base::Environment::Create());
@@ -332,11 +341,8 @@ std::string Uint256ValueToHex(uint256_t input) {
}
std::string GenerateMnemonic(size_t entropy_size) {
// entropy size should be 128, 160, 192, 224, 256 bits
if (entropy_size < 16 || entropy_size > 32 || entropy_size % 4 != 0) {
LOG(ERROR) << __func__ << ": Entropy should be 16, 20, 24, 28, 32 bytes";
if (!IsValidEntropySize(entropy_size))
return "";
}
std::vector<uint8_t> entropy(entropy_size);
crypto::RandBytes(&entropy[0], entropy.size());
@@ -352,10 +358,9 @@ std::string GenerateMnemonicForTest(const std::vector<uint8_t>& entropy) {
std::unique_ptr<std::vector<uint8_t>> MnemonicToSeed(
const std::string& mnemonic,
const std::string& passphrase) {
if (!IsValidMnemonic(mnemonic)) {
LOG(ERROR) << __func__ << ": Invalid mnemonic: " << mnemonic;
if (!IsValidMnemonic(mnemonic))
return nullptr;
}
std::unique_ptr<std::vector<uint8_t>> seed =
std::make_unique<std::vector<uint8_t>>(64);
const std::string salt = "mnemonic" + passphrase;
@@ -366,8 +371,54 @@ std::unique_ptr<std::vector<uint8_t>> MnemonicToSeed(
return rv == 1 ? std::move(seed) : nullptr;
}
std::unique_ptr<std::vector<uint8_t>> MnemonicToEntropy(
const std::string& mnemonic) {
if (!IsValidMnemonic(mnemonic))
return nullptr;
const std::vector<std::string> words = SplitString(
mnemonic, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
// size in bytes
size_t entropy_size = 0;
switch (words.size()) {
case 12:
entropy_size = 16;
break;
case 15:
entropy_size = 20;
break;
case 18:
entropy_size = 24;
break;
case 21:
entropy_size = 28;
break;
case 24:
entropy_size = 32;
break;
default:
NOTREACHED();
}
DCHECK(IsValidEntropySize(entropy_size)) << entropy_size;
std::unique_ptr<std::vector<uint8_t>> entropy =
std::make_unique<std::vector<uint8_t>>(entropy_size);
size_t written;
if (bip39_mnemonic_to_bytes(nullptr, mnemonic.c_str(), entropy->data(),
entropy->size(), &written) != WALLY_OK) {
LOG(ERROR) << "bip39_mnemonic_to_bytes failed";
return nullptr;
}
return entropy;
}
bool IsValidMnemonic(const std::string& mnemonic) {
return bip39_mnemonic_validate(nullptr, mnemonic.c_str()) == WALLY_OK;
if (bip39_mnemonic_validate(nullptr, mnemonic.c_str()) != WALLY_OK) {
LOG(ERROR) << __func__ << ": Invalid mnemonic: " << mnemonic;
return false;
}
return true;
}
bool EncodeString(const std::string& input, std::string* output) {
@@ -65,6 +65,9 @@ std::string GenerateMnemonicForTest(const std::vector<uint8_t>& entropy);
std::unique_ptr<std::vector<uint8_t>> MnemonicToSeed(
const std::string& mnemonic,
const std::string& passphrase);
// This is mainly used for restoring legacy brave crypto wallet
std::unique_ptr<std::vector<uint8_t>> MnemonicToEntropy(
const std::string& mnemonic);
bool IsValidMnemonic(const std::string& mnemonic);
bool EncodeString(const std::string& input, std::string* output);
@@ -292,6 +292,9 @@ TEST(BraveWalletUtilsUnitTest, Mnemonic) {
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); ++i) {
std::vector<uint8_t> bytes;
EXPECT_TRUE(base::HexStringToBytes(cases[i].entropy, &bytes));
std::unique_ptr<std::vector<uint8_t>> entropy =
MnemonicToEntropy(cases[i].mnemonic);
EXPECT_EQ(base::ToLowerASCII(base::HexEncode(*entropy)), cases[i].entropy);
EXPECT_EQ(GenerateMnemonicForTest(bytes), cases[i].mnemonic);
std::unique_ptr<std::vector<uint8_t>> seed =
@@ -315,21 +318,23 @@ TEST(BraveWalletUtilsUnitTest, Mnemonic) {
}
}
TEST(BraveWalletUtilsUnitTest, MnemonicToSeed) {
EXPECT_NE(MnemonicToSeed("kingdom possible coast island six arrow fluid "
"spell chunk loud glue street",
""),
nullptr);
EXPECT_EQ(MnemonicToSeed("lingdom possible coast island six arrow fluid "
"spell chunk loud glue street",
""),
nullptr);
EXPECT_EQ(
MnemonicToSeed(
"kingdom possible coast island six arrow fluid spell chunk loud glue",
""),
nullptr);
TEST(BraveWalletUtilsUnitTest, MnemonicToSeedAndEntropy) {
const char* valid_mnemonic =
"kingdom possible coast island six arrow fluid spell chunk loud glue "
"street";
const char* invalid_mnemonic1 =
"lingdom possible coast island six arrow fluid spell chunk loud glue "
"street";
const char* invalid_mnemonic2 =
"kingdom possible coast island six arrow fluid spell chunk loud glue";
EXPECT_NE(MnemonicToSeed(valid_mnemonic, ""), nullptr);
EXPECT_NE(MnemonicToEntropy(valid_mnemonic), nullptr);
EXPECT_EQ(MnemonicToSeed(invalid_mnemonic1, ""), nullptr);
EXPECT_EQ(MnemonicToEntropy(invalid_mnemonic1), nullptr);
EXPECT_EQ(MnemonicToSeed(invalid_mnemonic2, ""), nullptr);
EXPECT_EQ(MnemonicToEntropy(invalid_mnemonic2), nullptr);
EXPECT_EQ(MnemonicToSeed("", ""), nullptr);
EXPECT_EQ(MnemonicToEntropy(""), nullptr);
}
TEST(BraveWalletUtilsUnitTest, IsValidMnemonic) {
@@ -27,6 +27,7 @@
* { "default":
* { "backup_complete": false,
* "encrypted_mnemonic": [mnemonic],
* "legacy_brave_wallet": false,
* "account_metas": {
* "m/44'/60'/0'/0/0": {
* "account_name": "account 1",
@@ -69,6 +70,7 @@ const char kAccountName[] = "account_name";
const char kImportedAccounts[] = "imported_accounts";
const char kAccountAddress[] = "account_address";
const char kEncryptedPrivateKey[] = "encrypted_private_key";
const char kLegacyBraveWallet[] = "legacy_brave_wallet";
static base::span<const uint8_t> ToSpan(base::StringPiece sp) {
return base::as_bytes(base::make_span(sp));
@@ -298,7 +300,7 @@ KeyringController::GetImportedAccountsForKeyring(PrefService* prefs,
const std::string* encrypted_private_key =
imported_account.FindStringKey(kEncryptedPrivateKey);
if (!account_name || !account_address || !encrypted_private_key) {
LOG(ERROR) << "Imported accounts corruppted";
VLOG(0) << __func__ << "Imported accounts corruppted";
continue;
}
result.push_back(ImportedAccountInfo(
@@ -335,7 +337,7 @@ HDKeyring* KeyringController::CreateDefaultKeyring(
return nullptr;
const std::string mnemonic = GenerateMnemonic(16);
if (!CreateDefaultKeyringInternal(mnemonic)) {
if (!CreateDefaultKeyringInternal(mnemonic, false)) {
return nullptr;
}
@@ -353,7 +355,13 @@ HDKeyring* KeyringController::ResumeDefaultKeyring(
}
const std::string mnemonic = GetMnemonicForDefaultKeyringImpl();
if (mnemonic.empty() || !CreateDefaultKeyringInternal(mnemonic)) {
bool is_legacy_brave_wallet = false;
const base::Value* value =
GetPrefForKeyring(prefs_, kLegacyBraveWallet, kDefaultKeyringId);
if (value)
is_legacy_brave_wallet = value->GetBool();
if (mnemonic.empty() ||
!CreateDefaultKeyringInternal(mnemonic, is_legacy_brave_wallet)) {
return nullptr;
}
size_t account_no = GetAccountMetasNumberForKeyring(kDefaultKeyringId);
@@ -380,7 +388,8 @@ HDKeyring* KeyringController::ResumeDefaultKeyring(
HDKeyring* KeyringController::RestoreDefaultKeyring(
const std::string& mnemonic,
const std::string& password) {
const std::string& password,
bool is_legacy_brave_wallet) {
if (!IsValidMnemonic(mnemonic))
return nullptr;
@@ -388,7 +397,13 @@ HDKeyring* KeyringController::RestoreDefaultKeyring(
if (CreateEncryptorForKeyring(password, kDefaultKeyringId)) {
const std::string current_mnemonic = GetMnemonicForDefaultKeyringImpl();
// Restore with same mnmonic and same password, resume current keyring
if (!current_mnemonic.empty() && current_mnemonic == mnemonic) {
// Also need to make sure is_legacy_brave_wallet are the same, users might
// choose the option wrongly and then want to start over with same mnemonic
// but different is_legacy_brave_wallet value
const base::Value* value =
GetPrefForKeyring(prefs_, kLegacyBraveWallet, kDefaultKeyringId);
if (!current_mnemonic.empty() && current_mnemonic == mnemonic && value &&
value->GetBool() == is_legacy_brave_wallet) {
return ResumeDefaultKeyring(password);
} else {
// We have no way to check if new mnemonic is same as current mnemonic so
@@ -401,7 +416,7 @@ HDKeyring* KeyringController::RestoreDefaultKeyring(
return nullptr;
}
if (!CreateDefaultKeyringInternal(mnemonic)) {
if (!CreateDefaultKeyringInternal(mnemonic, is_legacy_brave_wallet)) {
return nullptr;
}
@@ -446,9 +461,11 @@ void KeyringController::CreateWallet(const std::string& password,
void KeyringController::RestoreWallet(const std::string& mnemonic,
const std::string& password,
bool is_legacy_brave_wallet,
RestoreWalletCallback callback) {
auto* keyring = RestoreDefaultKeyring(mnemonic, password);
if (keyring) {
auto* keyring =
RestoreDefaultKeyring(mnemonic, password, is_legacy_brave_wallet);
if (keyring && !keyring->GetAccountsNumber()) {
AddAccountForDefaultKeyring(kFirstAccountName);
}
// TODO(darkdh): add account discovery mechanism
@@ -458,7 +475,7 @@ void KeyringController::RestoreWallet(const std::string& mnemonic,
const std::string KeyringController::GetMnemonicForDefaultKeyringImpl() {
if (IsLocked()) {
LOG(ERROR) << __func__ << ": Must Unlock controller first";
VLOG(1) << __func__ << ": Must Unlock controller first";
return std::string();
}
DCHECK(encryptor_);
@@ -796,14 +813,24 @@ bool KeyringController::CreateEncryptorForKeyring(const std::string& password,
}
bool KeyringController::CreateDefaultKeyringInternal(
const std::string& mnemonic) {
const std::string& mnemonic,
bool is_legacy_brave_wallet) {
if (!encryptor_)
return false;
const std::unique_ptr<std::vector<uint8_t>> seed =
MnemonicToSeed(mnemonic, "");
std::unique_ptr<std::vector<uint8_t>> seed = nullptr;
if (is_legacy_brave_wallet)
seed = MnemonicToEntropy(mnemonic);
else
seed = MnemonicToSeed(mnemonic, "");
if (!seed)
return false;
if (is_legacy_brave_wallet && seed->size() != 32) {
VLOG(1) << __func__
<< "mnemonic for legacy brave wallet must be 24 words which will "
"produce 32 bytes seed";
return false;
}
std::vector<uint8_t> encrypted_mnemonic;
if (!encryptor_->Encrypt(ToSpan(mnemonic),
@@ -814,6 +841,12 @@ bool KeyringController::CreateDefaultKeyringInternal(
SetPrefInBytesForKeyring(kEncryptedMnemonic, encrypted_mnemonic,
kDefaultKeyringId);
if (is_legacy_brave_wallet)
SetPrefForKeyring(prefs_, kLegacyBraveWallet, base::Value(true),
kDefaultKeyringId);
else
SetPrefForKeyring(prefs_, kLegacyBraveWallet, base::Value(false),
kDefaultKeyringId);
default_keyring_ = std::make_unique<HDKeyring>();
default_keyring_->ConstructRootHDKey(*seed, kRootPath);
@@ -95,6 +95,7 @@ class KeyringController : public KeyedService, public mojom::KeyringController {
CreateWalletCallback callback) override;
void RestoreWallet(const std::string& mnemonic,
const std::string& password,
bool is_legacy_brave_wallet,
RestoreWalletCallback callback) override;
void Unlock(const std::string& password, UnlockCallback callback) override;
void Lock() override;
@@ -170,6 +171,7 @@ class KeyringController : public KeyedService, public mojom::KeyringController {
GetPrivateKeyForDefaultKeyringAccount);
FRIEND_TEST_ALL_PREFIXES(KeyringControllerUnitTest,
SetDefaultKeyringDerivedAccountName);
FRIEND_TEST_ALL_PREFIXES(KeyringControllerUnitTest, RestoreLegacyBraveWallet);
void AddAccountForDefaultKeyring(const std::string& account_name);
@@ -194,14 +196,16 @@ class KeyringController : public KeyedService, public mojom::KeyringController {
std::vector<uint8_t> GetOrCreateNonceForKeyring(const std::string& id);
bool CreateEncryptorForKeyring(const std::string& password,
const std::string& id);
bool CreateDefaultKeyringInternal(const std::string& mnemonic);
bool CreateDefaultKeyringInternal(const std::string& mnemonic,
bool is_legacy_brave_wallet);
// Currently only support one default keyring, `CreateDefaultKeyring` and
// `RestoreDefaultKeyring` will overwrite existing one if success
HDKeyring* CreateDefaultKeyring(const std::string& password);
// Restore default keyring from backup seed phrase
HDKeyring* RestoreDefaultKeyring(const std::string& mnemonic,
const std::string& password);
const std::string& password,
bool is_legacy_brave_wallet);
// It's used to reconstruct same default keyring between browser relaunch
HDKeyring* ResumeDefaultKeyring(const std::string& password);
@@ -184,7 +184,8 @@ interface ERCTokenRegistry {
interface KeyringController {
CreateWallet(string password) => (string mnemonic);
GetMnemonicForDefaultKeyring() => (string mnemonic);
RestoreWallet(string mnemonic, string password) => (bool isValidMnemonic);
RestoreWallet(string mnemonic, string password, bool isLegacyBraveWallet)
=> (bool isValidMnemonic);
Lock();
Unlock(string password) => (bool success);
IsLocked() => (bool isLocked);
@@ -507,7 +507,7 @@ export interface AssetRatioController {
export interface KeyringController {
createWallet: (password: string) => Promise<CreateWalletReturnInfo>
restoreWallet: (mnemonic: string, password: string) => Promise<RestoreWalletReturnInfo>
restoreWallet: (mnemonic: string, password: string, isLegacy: boolean) => Promise<RestoreWalletReturnInfo>
lock: () => Promise<void>
unlock: (password: string) => Promise<UnlockReturnInfo>
addAccount: (accountName: string) => Promise<AddAccountReturnInfo>
@@ -45,7 +45,7 @@ handler.on(WalletPageActions.createWallet.getType(), async (store, payload: Crea
handler.on(WalletPageActions.restoreWallet.getType(), async (store, payload: RestoreWalletPayloadType) => {
const keyringController = (await getAPIProxy()).keyringController
const result = await keyringController.restoreWallet(payload.mnemonic, payload.password)
const result = await keyringController.restoreWallet(payload.mnemonic, payload.password, payload.isLegacy)
if (!result.isValidMnemonic) {
store.dispatch(WalletPageActions.hasMnemonicError(!result.isValidMnemonic))
return
@@ -34,7 +34,8 @@ export type RemoveImportedAccountPayloadType = {
export type RestoreWalletPayloadType = {
mnemonic: string,
password: string
password: string,
isLegacy: boolean
}
export type WalletCreatedPayloadType = {
@@ -204,7 +204,7 @@ function Container (props: Props) {
const restoreWallet = (mnemonic: string, password: string, isLegacy: boolean) => {
// isLegacy prop will be passed into the restoreWallet action once the keyring is setup handle the derivation.
props.walletPageActions.restoreWallet({ mnemonic, password })
props.walletPageActions.restoreWallet({ mnemonic, password, isLegacy })
}
const passwordProvided = (password: string) => {
@@ -136,7 +136,7 @@ export const _DesktopWalletConcept = (args: { onboarding: boolean, locked: boole
setShowBackup(false)
}
const onRestore = (phrase: string, password: string) => {
const onRestore = (phrase: string, password: string, isLegacy: boolean) => {
if (JSON.stringify(phrase.split(' ')) === JSON.stringify(recoveryPhrase)) {
completeWalletSetup(true)
} else {