@@ -134,6 +134,9 @@ UniValue importprivkey(const JSONRPCRequest& request)
134134 },
135135 }.ToString ());
136136
137+ if (pwallet->IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
138+ throw JSONRPCError (RPC_WALLET_ERROR, " Cannot import private keys to a wallet with private keys disabled" );
139+ }
137140
138141 WalletRescanReserver reserver (pwallet);
139142 bool fRescan = true ;
@@ -587,8 +590,10 @@ UniValue importwallet(const JSONRPCRequest& request)
587590 // Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which
588591 // we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button.
589592 uiInterface.ShowProgress (strprintf (" %s " + _ (" Importing..." ), pwallet->GetDisplayName ()), 0 , false ); // show progress dialog in GUI
593+ std::vector<std::tuple<CKey, int64_t , bool , std::string>> keys;
594+ std::vector<std::pair<CScript, int64_t >> scripts;
590595 while (file.good ()) {
591- uiInterface.ShowProgress (" " , std::max (1 , std::min (99 , (int )(((double )file.tellg () / (double )nFilesize) * 100 ))), false );
596+ uiInterface.ShowProgress (" " , std::max (1 , std::min (50 , (int )(((double )file.tellg () / (double )nFilesize) * 100 ))), false );
592597 std::string line;
593598 std::getline (file, line);
594599 if (line.empty () || line[0 ] == ' #' )
@@ -600,13 +605,6 @@ UniValue importwallet(const JSONRPCRequest& request)
600605 continue ;
601606 CKey key = DecodeSecret (vstr[0 ]);
602607 if (key.IsValid ()) {
603- CPubKey pubkey = key.GetPubKey ();
604- assert (key.VerifyPubKey (pubkey));
605- CKeyID keyid = pubkey.GetID ();
606- if (pwallet->HaveKey (keyid)) {
607- pwallet->WalletLogPrintf (" Skipping import of %s (key already present)\n " , EncodeDestination (keyid));
608- continue ;
609- }
610608 int64_t nTime = DecodeDumpTime (vstr[1 ]);
611609 std::string strLabel;
612610 bool fLabel = true ;
@@ -622,36 +620,67 @@ UniValue importwallet(const JSONRPCRequest& request)
622620 fLabel = true ;
623621 }
624622 }
625- pwallet->WalletLogPrintf (" Importing %s...\n " , EncodeDestination (keyid));
626- if (!pwallet->AddKeyPubKey (key, pubkey)) {
627- fGood = false ;
628- continue ;
629- }
630- pwallet->mapKeyMetadata [keyid].nCreateTime = nTime;
631- if (fLabel )
632- pwallet->SetAddressBook (keyid, strLabel, " receive" );
633- nTimeBegin = std::min (nTimeBegin, nTime);
623+ keys.push_back (std::make_tuple (key, nTime, fLabel , strLabel));
634624 } else if (IsHex (vstr[0 ])) {
635- std::vector<unsigned char > vData (ParseHex (vstr[0 ]));
636- CScript script = CScript (vData.begin (), vData.end ());
637- CScriptID id (script);
638- if (pwallet->HaveCScript (id)) {
639- pwallet->WalletLogPrintf (" Skipping import of %s (script already present)\n " , vstr[0 ]);
640- continue ;
641- }
642- if (!pwallet->AddCScript (script)) {
643- pwallet->WalletLogPrintf (" Error importing script %s\n " , vstr[0 ]);
644- fGood = false ;
645- continue ;
646- }
647- int64_t birth_time = DecodeDumpTime (vstr[1 ]);
648- if (birth_time > 0 ) {
649- pwallet->m_script_metadata [id].nCreateTime = birth_time;
650- nTimeBegin = std::min (nTimeBegin, birth_time);
651- }
625+ std::vector<unsigned char > vData (ParseHex (vstr[0 ]));
626+ CScript script = CScript (vData.begin (), vData.end ());
627+ int64_t birth_time = DecodeDumpTime (vstr[1 ]);
628+ scripts.push_back (std::pair<CScript, int64_t >(script, birth_time));
652629 }
653630 }
654631 file.close ();
632+ // We now know whether we are importing private keys, so we can error if private keys are disabled
633+ if (keys.size () > 0 && pwallet->IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
634+ uiInterface.ShowProgress (" " , 100 , false ); // hide progress dialog in GUI
635+ throw JSONRPCError (RPC_WALLET_ERROR, " Importing wallets is disabled when private keys are disabled" );
636+ }
637+ double total = (double )(keys.size () + scripts.size ());
638+ double progress = 0 ;
639+ for (const auto & key_tuple : keys) {
640+ uiInterface.ShowProgress (" " , std::max (50 , std::min (75 , (int )((progress / total) * 100 ) + 50 )), false );
641+ const CKey& key = std::get<0 >(key_tuple);
642+ int64_t time = std::get<1 >(key_tuple);
643+ bool has_label = std::get<2 >(key_tuple);
644+ std::string label = std::get<3 >(key_tuple);
645+
646+ CPubKey pubkey = key.GetPubKey ();
647+ assert (key.VerifyPubKey (pubkey));
648+ CKeyID keyid = pubkey.GetID ();
649+ if (pwallet->HaveKey (keyid)) {
650+ pwallet->WalletLogPrintf (" Skipping import of %s (key already present)\n " , EncodeDestination (keyid));
651+ continue ;
652+ }
653+ pwallet->WalletLogPrintf (" Importing %s...\n " , EncodeDestination (keyid));
654+ if (!pwallet->AddKeyPubKey (key, pubkey)) {
655+ fGood = false ;
656+ continue ;
657+ }
658+ pwallet->mapKeyMetadata [keyid].nCreateTime = time;
659+ if (has_label)
660+ pwallet->SetAddressBook (keyid, label, " receive" );
661+ nTimeBegin = std::min (nTimeBegin, time);
662+ progress++;
663+ }
664+ for (const auto & script_pair : scripts) {
665+ uiInterface.ShowProgress (" " , std::max (50 , std::min (75 , (int )((progress / total) * 100 ) + 50 )), false );
666+ const CScript& script = script_pair.first ;
667+ int64_t time = script_pair.second ;
668+ CScriptID id (script);
669+ if (pwallet->HaveCScript (id)) {
670+ pwallet->WalletLogPrintf (" Skipping import of %s (script already present)\n " , HexStr (script));
671+ continue ;
672+ }
673+ if (!pwallet->AddCScript (script)) {
674+ pwallet->WalletLogPrintf (" Error importing script %s\n " , HexStr (script));
675+ fGood = false ;
676+ continue ;
677+ }
678+ if (time > 0 ) {
679+ pwallet->m_script_metadata [id].nCreateTime = time;
680+ nTimeBegin = std::min (nTimeBegin, time);
681+ }
682+ progress++;
683+ }
655684 uiInterface.ShowProgress (" " , 100 , false ); // hide progress dialog in GUI
656685 pwallet->UpdateTimeFirstKey (nTimeBegin);
657686 }
@@ -958,6 +987,11 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
958987 const bool watchOnly = data.exists (" watchonly" ) ? data[" watchonly" ].get_bool () : false ;
959988 const std::string& label = data.exists (" label" ) ? data[" label" ].get_str () : " " ;
960989
990+ // If private keys are disabled, abort if private keys are being imported
991+ if (pwallet->IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.isNull ()) {
992+ throw JSONRPCError (RPC_WALLET_ERROR, " Cannot import private keys to a wallet with private keys disabled" );
993+ }
994+
961995 // Generate the script and destination for the scriptPubKey provided
962996 CScript script;
963997 CTxDestination dest;
0 commit comments