Skip to content

Commit 4fcccda

Browse files
author
MarcoFalke
committed
Merge #16244: Move wallet creation out of the createwallet rpc into its own function
1aecdf2 Move wallet creation out of the createwallet rpc into its own function (Andrew Chow) Pull request description: Moves the wallet creation logic from within the `createwallet` rpc and into its own function within wallet.cpp. ACKs for top commit: jnewbery: ACK 1aecdf2 MarcoFalke: ACK 1aecdf2 Sjors: ACK 1aecdf2 with some suggestions for followup. Tree-SHA512: 8d26d7ff48db4f8fac12408a5a294f788b7f50a72e7eb4008fb74ff14d7400eb3970f8038a19f989eff55198fc11c0cf86f52231c62b9015eb777132edc8ea88
2 parents ff0aad8 + 1aecdf2 commit 4fcccda

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
@@ -2660,17 +2660,12 @@ static UniValue createwallet(const JSONRPCRequest& request)
26602660
},
26612661
}.Check(request);
26622662

2663-
std::string error;
2664-
std::string warning;
2665-
26662663
uint64_t flags = 0;
26672664
if (!request.params[1].isNull() && request.params[1].get_bool()) {
26682665
flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS;
26692666
}
26702667

2671-
bool create_blank = false; // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
26722668
if (!request.params[2].isNull() && request.params[2].get_bool()) {
2673-
create_blank = true;
26742669
flags |= WALLET_FLAG_BLANK_WALLET;
26752670
}
26762671
SecureString passphrase;
@@ -2681,55 +2676,24 @@ static UniValue createwallet(const JSONRPCRequest& request)
26812676
// Empty string is invalid
26822677
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Cannot encrypt a wallet with a blank password");
26832678
}
2684-
// Born encrypted wallets need to be blank first so that wallet creation doesn't make any unencrypted keys
2685-
flags |= WALLET_FLAG_BLANK_WALLET;
26862679
}
26872680

26882681
if (!request.params[4].isNull() && request.params[4].get_bool()) {
26892682
flags |= WALLET_FLAG_AVOID_REUSE;
26902683
}
26912684

2692-
WalletLocation location(request.params[0].get_str());
2693-
if (location.Exists()) {
2694-
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet " + location.GetName() + " already exists.");
2695-
}
2696-
2697-
// Wallet::Verify will check if we're trying to create a wallet with a duplication name.
2698-
if (!CWallet::Verify(*g_rpc_interfaces->chain, location, false, error, warning)) {
2699-
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
2700-
}
2701-
2702-
std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(*g_rpc_interfaces->chain, location, flags);
2703-
if (!wallet) {
2704-
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed.");
2705-
}
2706-
2707-
// Encrypt the wallet if there's a passphrase
2708-
if (!passphrase.empty() && !(flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
2709-
if (!wallet->EncryptWallet(passphrase)) {
2710-
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Wallet created but failed to encrypt.");
2711-
}
2712-
2713-
if (!create_blank) {
2714-
// Unlock the wallet
2715-
if (!wallet->Unlock(passphrase)) {
2716-
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Wallet was encrypted but could not be unlocked");
2717-
}
2718-
2719-
// Set a seed for the wallet
2720-
CPubKey master_pub_key = wallet->GenerateNewSeed();
2721-
wallet->SetHDSeed(master_pub_key);
2722-
wallet->NewKeyPool();
2723-
2724-
// Relock the wallet
2725-
wallet->Lock();
2726-
}
2685+
std::string error;
2686+
std::string warning;
2687+
WalletCreationStatus status;
2688+
std::shared_ptr<CWallet> wallet = CreateWallet(*g_rpc_interfaces->chain, request.params[0].get_str(), error, warning, status, passphrase, flags);
2689+
if (status == WalletCreationStatus::CREATION_FAILED) {
2690+
throw JSONRPCError(RPC_WALLET_ERROR, error);
2691+
} else if (status == WalletCreationStatus::ENCRYPTION_FAILED) {
2692+
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, error);
2693+
} else if (status != WalletCreationStatus::SUCCESS) {
2694+
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed");
27272695
}
27282696

2729-
AddWallet(wallet);
2730-
2731-
wallet->postInitProcess();
2732-
27332697
UniValue obj(UniValue::VOBJ);
27342698
obj.pushKV("name", wallet->GetName());
27352699
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)