| 281 | } |
| 282 | |
| 283 | std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings) |
| 284 | { |
| 285 | uint64_t wallet_creation_flags = options.create_flags; |
| 286 | const SecureString& passphrase = options.create_passphrase; |
| 287 | |
| 288 | if (wallet_creation_flags & WALLET_FLAG_DESCRIPTORS) options.require_format = DatabaseFormat::SQLITE; |
| 289 | |
| 290 | // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted |
| 291 | bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET); |
| 292 | |
| 293 | // Born encrypted wallets need to be created blank first. |
| 294 | if (!passphrase.empty()) { |
| 295 | wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET; |
| 296 | } |
| 297 | |
| 298 | // Private keys must be disabled for an external signer wallet |
| 299 | if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { |
| 300 | error = Untranslated("Private keys must be disabled when using an external signer"); |
| 301 | status = DatabaseStatus::FAILED_CREATE; |
| 302 | return nullptr; |
| 303 | } |
| 304 | |
| 305 | // Descriptor support must be enabled for an external signer wallet |
| 306 | if ((wallet_creation_flags & WALLET_FLAG_EXTERNAL_SIGNER) && !(wallet_creation_flags & WALLET_FLAG_DESCRIPTORS)) { |
| 307 | error = Untranslated("Descriptor support must be enabled when using an external signer"); |
| 308 | status = DatabaseStatus::FAILED_CREATE; |
| 309 | return nullptr; |
| 310 | } |
| 311 | |
| 312 | // Wallet::Verify will check if we're trying to create a wallet with a duplicate name. |
| 313 | std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error); |
| 314 | if (!database) { |
| 315 | error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error; |
| 316 | status = DatabaseStatus::FAILED_VERIFY; |
| 317 | return nullptr; |
| 318 | } |
| 319 | |
| 320 | // Do not allow a passphrase when private keys are disabled |
| 321 | if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { |
| 322 | error = Untranslated("Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled."); |
| 323 | status = DatabaseStatus::FAILED_CREATE; |
| 324 | return nullptr; |
| 325 | } |
| 326 | |
| 327 | // Make the wallet |
| 328 | context.chain->initMessage(_("Loading wallet…").translated); |
| 329 | const std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), wallet_creation_flags, error, warnings); |
| 330 | if (!wallet) { |
| 331 | error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error; |
| 332 | status = DatabaseStatus::FAILED_CREATE; |
| 333 | return nullptr; |
| 334 | } |
| 335 | |
| 336 | // Encrypt the wallet |
| 337 | if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { |
| 338 | if (!wallet->EncryptWallet(passphrase)) { |
| 339 | error = Untranslated("Error: Wallet created but failed to encrypt."); |
| 340 | status = DatabaseStatus::FAILED_ENCRYPT; |