Skip to content

Commit 1aecdf2

Browse files
committed
Move wallet creation out of the createwallet rpc into its own function
1 parent 357488f commit 1aecdf2

File tree

3 files changed

+82
-46
lines changed

3 files changed

+82
-46
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2677,17 +2677,12 @@ static UniValue createwallet(const JSONRPCRequest& request)
26772677
},
26782678
}.Check(request);
26792679

2680-
std::string error;
2681-
std::string warning;
2682-
26832680
uint64_t flags = 0;
26842681
if (!request.params[1].isNull() && request.params[1].get_bool()) {
26852682
flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS;
26862683
}
26872684

2688-
bool create_blank = false; // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
26892685
if (!request.params[2].isNull() && request.params[2].get_bool()) {
2690-
create_blank = true;
26912686
flags |= WALLET_FLAG_BLANK_WALLET;
26922687
}
26932688
SecureString passphrase;
@@ -2698,55 +2693,24 @@ static UniValue createwallet(const JSONRPCRequest& request)
26982693
// Empty string is invalid
26992694
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Cannot encrypt a wallet with a blank password");
27002695
}
2701-
// Born encrypted wallets need to be blank first so that wallet creation doesn't make any unencrypted keys
2702-
flags |= WALLET_FLAG_BLANK_WALLET;
27032696
}
27042697

27052698
if (!request.params[4].isNull() && request.params[4].get_bool()) {
27062699
flags |= WALLET_FLAG_AVOID_REUSE;
27072700
}
27082701

2709-
WalletLocation location(request.params[0].get_str());
2710-
if (location.Exists()) {
2711-
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet " + location.GetName() + " already exists.");
2712-
}
2713-
2714-
// Wallet::Verify will check if we're trying to create a wallet with a duplication name.
2715-
if (!CWallet::Verify(*g_rpc_interfaces->chain, location, false, error, warning)) {
2716-
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
2717-
}
2718-
2719-
std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(*g_rpc_interfaces->chain, location, flags);
2720-
if (!wallet) {
2721-
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed.");
2722-
}
2723-
2724-
// Encrypt the wallet if there's a passphrase
2725-
if (!passphrase.empty() && !(flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
2726-
if (!wallet->EncryptWallet(passphrase)) {
2727-
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Wallet created but failed to encrypt.");
2728-
}
2729-
2730-
if (!create_blank) {
2731-
// Unlock the wallet
2732-
if (!wallet->Unlock(passphrase)) {
2733-
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Wallet was encrypted but could not be unlocked");
2734-
}
2735-
2736-
// Set a seed for the wallet
2737-
CPubKey master_pub_key = wallet->GenerateNewSeed();
2738-
wallet->SetHDSeed(master_pub_key);
2739-
wallet->NewKeyPool();
2740-
2741-
// Relock the wallet
2742-
wallet->Lock();
2743-
}
2702+
std::string error;
2703+
std::string warning;
2704+
WalletCreationStatus status;
2705+
std::shared_ptr<CWallet> wallet = CreateWallet(*g_rpc_interfaces->chain, request.params[0].get_str(), error, warning, status, passphrase, flags);
2706+
if (status == WalletCreationStatus::CREATION_FAILED) {
2707+
throw JSONRPCError(RPC_WALLET_ERROR, error);
2708+
} else if (status == WalletCreationStatus::ENCRYPTION_FAILED) {
2709+
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, error);
2710+
} else if (status != WalletCreationStatus::SUCCESS) {
2711+
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed");
27442712
}
27452713

2746-
AddWallet(wallet);
2747-
2748-
wallet->postInitProcess();
2749-
27502714
UniValue obj(UniValue::VOBJ);
27512715
obj.pushKV("name", wallet->GetName());
27522716
obj.pushKV("warning", warning);

src/wallet/wallet.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,70 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string&
160160
return LoadWallet(chain, WalletLocation(name), error, warning);
161161
}
162162

163+
std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning, WalletCreationStatus& status, const SecureString& passphrase, uint64_t wallet_creation_flags)
164+
{
165+
// Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
166+
bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
167+
168+
// Born encrypted wallets need to be created blank first.
169+
if (!passphrase.empty()) {
170+
wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
171+
}
172+
173+
// Check the wallet file location
174+
WalletLocation location(name);
175+
if (location.Exists()) {
176+
error = "Wallet " + location.GetName() + " already exists.";
177+
status = WalletCreationStatus::CREATION_FAILED;
178+
return nullptr;
179+
}
180+
181+
// Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
182+
std::string wallet_error;
183+
if (!CWallet::Verify(chain, location, false, wallet_error, warning)) {
184+
error = "Wallet file verification failed: " + wallet_error;
185+
status = WalletCreationStatus::CREATION_FAILED;
186+
return nullptr;
187+
}
188+
189+
// Make the wallet
190+
std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, wallet_creation_flags);
191+
if (!wallet) {
192+
error = "Wallet creation failed";
193+
status = WalletCreationStatus::CREATION_FAILED;
194+
return nullptr;
195+
}
196+
197+
// Encrypt the wallet
198+
if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
199+
if (!wallet->EncryptWallet(passphrase)) {
200+
error = "Error: Wallet created but failed to encrypt.";
201+
status = WalletCreationStatus::ENCRYPTION_FAILED;
202+
return nullptr;
203+
}
204+
if (!create_blank) {
205+
// Unlock the wallet
206+
if (!wallet->Unlock(passphrase)) {
207+
error = "Error: Wallet was encrypted but could not be unlocked";
208+
status = WalletCreationStatus::ENCRYPTION_FAILED;
209+
return nullptr;
210+
}
211+
212+
// Set a seed for the wallet
213+
CPubKey master_pub_key = wallet->GenerateNewSeed();
214+
wallet->SetHDSeed(master_pub_key);
215+
wallet->NewKeyPool();
216+
217+
// Relock the wallet
218+
wallet->Lock();
219+
}
220+
}
221+
AddWallet(wallet);
222+
wallet->postInitProcess();
223+
status = WalletCreationStatus::SUCCESS;
224+
return wallet;
225+
}
226+
163227
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
164228

165229
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));

src/wallet/wallet.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ std::vector<std::shared_ptr<CWallet>> GetWallets();
4949
std::shared_ptr<CWallet> GetWallet(const std::string& name);
5050
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning);
5151

52+
enum WalletCreationStatus {
53+
SUCCESS,
54+
CREATION_FAILED,
55+
ENCRYPTION_FAILED
56+
};
57+
58+
std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning, WalletCreationStatus& status, const SecureString& passphrase, uint64_t wallet_creation_flags);
59+
5260
//! Default for -keypool
5361
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
5462
//! -paytxfee default

0 commit comments

Comments
 (0)