@@ -134,6 +134,9 @@ UniValue importprivkey(const JSONRPCRequest& request)
134
134
},
135
135
}.ToString ());
136
136
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
+ }
137
140
138
141
WalletRescanReserver reserver (pwallet);
139
142
bool fRescan = true ;
@@ -587,8 +590,10 @@ UniValue importwallet(const JSONRPCRequest& request)
587
590
// Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which
588
591
// we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button.
589
592
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;
590
595
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 );
592
597
std::string line;
593
598
std::getline (file, line);
594
599
if (line.empty () || line[0 ] == ' #' )
@@ -600,13 +605,6 @@ UniValue importwallet(const JSONRPCRequest& request)
600
605
continue ;
601
606
CKey key = DecodeSecret (vstr[0 ]);
602
607
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
- }
610
608
int64_t nTime = DecodeDumpTime (vstr[1 ]);
611
609
std::string strLabel;
612
610
bool fLabel = true ;
@@ -622,36 +620,67 @@ UniValue importwallet(const JSONRPCRequest& request)
622
620
fLabel = true ;
623
621
}
624
622
}
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));
634
624
} 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));
652
629
}
653
630
}
654
631
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
+ }
655
684
uiInterface.ShowProgress (" " , 100 , false ); // hide progress dialog in GUI
656
685
pwallet->UpdateTimeFirstKey (nTimeBegin);
657
686
}
@@ -958,6 +987,11 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
958
987
const bool watchOnly = data.exists (" watchonly" ) ? data[" watchonly" ].get_bool () : false ;
959
988
const std::string& label = data.exists (" label" ) ? data[" label" ].get_str () : " " ;
960
989
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
+
961
995
// Generate the script and destination for the scriptPubKey provided
962
996
CScript script;
963
997
CTxDestination dest;
0 commit comments