Skip to content

Commit 98086de

Browse files
authored
Merge pull request duality-solutions#343 from duality-solutions/v2.4.19-importprivkey
Update importprivkey and wallet methods to ensure keypools stay in sync
2 parents b9aa31f + e667094 commit 98086de

File tree

6 files changed

+47
-183
lines changed

6 files changed

+47
-183
lines changed

src/qt/forms/mnemonicdialog.ui

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -664,16 +664,6 @@ Wallet wil restart after mnemonic has been imported.</string>
664664
</property>
665665
</spacer>
666666
</item>
667-
<item>
668-
<widget class="QCheckBox" name="checkBoxPrivateKeyForceRescan">
669-
<property name="text">
670-
<string>Force Rescan</string>
671-
</property>
672-
<property name="checked">
673-
<bool>true</bool>
674-
</property>
675-
</widget>
676-
</item>
677667
</layout>
678668
</item>
679669
<item>

src/qt/mnemonicdialog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ void MnemonicDialog::combobox2ItemChanged(int input)
115115

116116
void MnemonicDialog::on_importPrivatekey_clicked()
117117
{
118-
bool ForceRescan = ui->checkBoxPrivateKeyForceRescan->isChecked();
118+
bool ForceRescan = true;
119119

120120
importPrivatekey(ForceRescan);
121121
}

src/wallet/rpcdump.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,15 @@ UniValue importprivkey(const JSONRPCRequest& request)
152152
if (!pwalletMain->AddKeyPubKey(key, pubkey))
153153
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
154154

155+
pwalletMain->GenerateEdandStealthKey(key);
156+
155157
// whenever a key is imported, we need to scan the whole chain
156158
pwalletMain->UpdateTimeFirstKey(1);
157159
}
158160

159161
if (fRescan || !isskip) {
162+
pwalletMain->SetUpdateKeyPoolsAndLinks();
163+
160164
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
161165
}
162166
}
@@ -858,7 +862,6 @@ UniValue importmnemonic(const JSONRPCRequest& request)
858862
if (!EnsureWalletIsAvailable(request.fHelp)) {
859863
return NullUniValue;
860864
}
861-
862865

863866
LOCK2(cs_main, pwalletMain->cs_wallet);
864867
UniValue entry(UniValue::VOBJ);

src/wallet/rpcwallet.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ UniValue getnewaddress(const JSONRPCRequest& request)
131131
strAccount = AccountFromValue(request.params[0]);
132132

133133
if (!pwalletMain->IsLocked(true))
134-
pwalletMain->TopUpKeyPool();
134+
pwalletMain->TopUpKeyPoolCombo();
135135

136136
// Generate a new key that is added to wallet
137137
CPubKey newKey;
@@ -278,7 +278,7 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request)
278278
LOCK2(cs_main, pwalletMain->cs_wallet);
279279

280280
if (!pwalletMain->IsLocked(true))
281-
pwalletMain->TopUpKeyPool();
281+
pwalletMain->TopUpKeyPoolCombo();
282282

283283
CReserveKey reservekey(pwalletMain);
284284
CPubKey vchPubKey;
@@ -2196,7 +2196,7 @@ UniValue keypoolrefill(const JSONRPCRequest& request)
21962196
}
21972197

21982198
EnsureWalletIsUnlocked();
2199-
pwalletMain->TopUpKeyPool(kpSize);
2199+
pwalletMain->TopUpKeyPoolCombo(kpSize);
22002200

22012201
if (pwalletMain->GetKeyPoolSize() < (pwalletMain->IsHDEnabled() ? kpSize * 2 : kpSize))
22022202
throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");

src/wallet/wallet.cpp

Lines changed: 30 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
114114
return &(it->second);
115115
}
116116

117+
void CWallet::GenerateEdandStealthKey(CKey& keyIn)
118+
{
119+
CKeyEd25519 secretEdRet;
120+
DeriveEd25519ChildKey(keyIn,secretEdRet); //Derive Ed25519 key
121+
DeriveChildStealthKey(keyIn); //Derive stealth key
122+
}
123+
117124
CPubKey CWallet::GenerateNewKey(uint32_t nAccountIndex, bool fInternal)
118125
{
119126
AssertLockHeld(cs_wallet); // mapKeyMetadata
@@ -4570,69 +4577,6 @@ bool CWallet::SyncEdKeyPool()
45704577

45714578
} //SyncEdKeyPool
45724579

4573-
4574-
4575-
4576-
bool CWallet::TopUpKeyPool(unsigned int kpSize)
4577-
{
4578-
{
4579-
LOCK(cs_wallet);
4580-
4581-
if (IsLocked(true))
4582-
return false;
4583-
4584-
// Top up key pool
4585-
unsigned int nTargetSize;
4586-
if (kpSize > 0)
4587-
nTargetSize = kpSize;
4588-
else
4589-
nTargetSize = std::max(GetArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t)0);
4590-
4591-
// count amount of available keys (internal, external)
4592-
// make sure the keypool of external and internal keys fits the user selected target (-keypool)
4593-
int64_t amountExternal = setExternalKeyPool.size();
4594-
int64_t amountInternal = setInternalKeyPool.size();
4595-
int64_t missingExternal = std::max(std::max((int64_t)nTargetSize, (int64_t)1) - amountExternal, (int64_t)0);
4596-
int64_t missingInternal = std::max(std::max((int64_t)nTargetSize, (int64_t)1) - amountInternal, (int64_t)0);
4597-
4598-
if (!IsHDEnabled()) {
4599-
// don't create extra internal keys
4600-
missingInternal = 0;
4601-
} else {
4602-
nTargetSize *= 2;
4603-
}
4604-
bool fInternal = false;
4605-
CWalletDB walletdb(strWalletFile);
4606-
for (int64_t i = missingInternal + missingExternal; i--;) {
4607-
int64_t nEnd = 1;
4608-
if (i < missingInternal) {
4609-
fInternal = true;
4610-
}
4611-
if (!setInternalKeyPool.empty()) {
4612-
nEnd = *(--setInternalKeyPool.end()) + 1;
4613-
}
4614-
if (!setExternalKeyPool.empty()) {
4615-
nEnd = std::max(nEnd, *(--setExternalKeyPool.end()) + 1);
4616-
}
4617-
// TODO: implement keypools for all accounts?
4618-
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey(0, fInternal), fInternal)))
4619-
throw std::runtime_error("TopUpKeyPool(): writing generated key failed");
4620-
4621-
if (fInternal) {
4622-
setInternalKeyPool.insert(nEnd);
4623-
} else {
4624-
setExternalKeyPool.insert(nEnd);
4625-
}
4626-
LogPrintf("keypool added key %d, size=%u, internal=%d\n", nEnd, setInternalKeyPool.size() + setExternalKeyPool.size(), fInternal);
4627-
4628-
double dProgress = 100.f * nEnd / (nTargetSize + 1);
4629-
std::string strMsg = strprintf(_("Loading wallet... (%3.2f %%)"), dProgress);
4630-
uiInterface.InitMessage(strMsg);
4631-
}
4632-
}
4633-
return true;
4634-
}
4635-
46364580
bool CWallet::TopUpKeyPoolCombo(unsigned int kpSize)
46374581
{
46384582
{
@@ -4696,7 +4640,7 @@ bool CWallet::TopUpKeyPoolCombo(unsigned int kpSize)
46964640

46974641
// TODO: implement keypools for all accounts?
46984642
if (!walletdb.WriteEdPool(nEnd, CEdKeyPool(GenerateNewEdKey(0, fInternal, retrievedKey), fInternal)))
4699-
throw std::runtime_error("TopUpEdKeyPool(): writing generated key failed");
4643+
throw std::runtime_error("TopUpKeyPoolCombo(): writing generated key failed");
47004644

47014645
if (fInternal) {
47024646
setInternalEdKeyPool.insert(nEnd);
@@ -4713,63 +4657,6 @@ bool CWallet::TopUpKeyPoolCombo(unsigned int kpSize)
47134657
return true;
47144658
} //TopUpKeyPoolCombo
47154659

4716-
bool CWallet::TopUpEdKeyPool(unsigned int kpSize)
4717-
{
4718-
{
4719-
LOCK(cs_wallet);
4720-
4721-
if (IsLocked(true))
4722-
return false;
4723-
4724-
// Top up key pool
4725-
unsigned int nTargetSize;
4726-
if (kpSize > 0)
4727-
nTargetSize = kpSize;
4728-
else
4729-
nTargetSize = std::max(GetArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t)0);
4730-
4731-
// count amount of available keys (internal, external)
4732-
// make sure the keypool of external and internal keys fits the user selected target (-keypool)
4733-
int64_t amountExternal = setExternalEdKeyPool.size();
4734-
int64_t amountInternal = setInternalEdKeyPool.size();
4735-
int64_t missingExternal = std::max(std::max((int64_t)nTargetSize, (int64_t)1) - amountExternal, (int64_t)0);
4736-
int64_t missingInternal = std::max(std::max((int64_t)nTargetSize, (int64_t)1) - amountInternal, (int64_t)0);
4737-
4738-
if (!IsHDEnabled()) {
4739-
// don't create extra internal keys
4740-
missingInternal = 0;
4741-
} else {
4742-
nTargetSize *= 2;
4743-
}
4744-
bool fInternal = false;
4745-
CWalletDB walletdb(strWalletFile);
4746-
for (int64_t i = missingInternal + missingExternal; i--;) {
4747-
int64_t nEnd = 1;
4748-
if (i < missingInternal) {
4749-
fInternal = true;
4750-
}
4751-
if (!setInternalEdKeyPool.empty()) {
4752-
nEnd = *(--setInternalEdKeyPool.end()) + 1;
4753-
}
4754-
if (!setExternalEdKeyPool.empty()) {
4755-
nEnd = std::max(nEnd, *(--setExternalEdKeyPool.end()) + 1);
4756-
}
4757-
// TODO: implement keypools for all accounts?
4758-
if (!walletdb.WriteEdPool(nEnd, CEdKeyPool(GenerateNewEdKey(0, fInternal), fInternal)))
4759-
throw std::runtime_error("TopUpEdKeyPool(): writing generated key failed");
4760-
4761-
if (fInternal) {
4762-
setInternalEdKeyPool.insert(nEnd);
4763-
} else {
4764-
setExternalEdKeyPool.insert(nEnd);
4765-
}
4766-
LogPrintf("edkeypool added key %d, size=%u, internal=%d\n", nEnd, setInternalEdKeyPool.size() + setExternalEdKeyPool.size(), fInternal);
4767-
4768-
}
4769-
}
4770-
return true;
4771-
} //TopUpEdKeyPool
4772-
47734660
void CWallet::UpdateKeyPoolsFromTransactions(const std::string& strOpType, const std::vector<std::vector<unsigned char>>& vvchOpParameters)
47744661
{
47754662
std::vector<unsigned char> key0 = vvchOpParameters[0];
@@ -4785,9 +4672,11 @@ void CWallet::UpdateKeyPoolsFromTransactions(const std::string& strOpType, const
47854672

47864673
} //UpdateKeyPoolsFromTransactions
47874674

4788-
void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fInternal)
4675+
4676+
void CWallet::ReserveKeysFromKeyPools(int64_t& nIndex, CKeyPool& keypool, CEdKeyPool& edkeypool, bool fInternal)
47894677
{
47904678
nIndex = -1;
4679+
int64_t nEdIndex = nIndex;
47914680
keypool.vchPubKey = CPubKey();
47924681
{
47934682
LOCK(cs_wallet);
@@ -4797,6 +4686,7 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fIn
47974686

47984687
fInternal = fInternal && IsHDEnabled();
47994688
std::set<int64_t>& setKeyPool = fInternal ? setInternalKeyPool : setExternalKeyPool;
4689+
std::set<int64_t>& setEdKeyPool = fInternal ? setInternalEdKeyPool : setExternalEdKeyPool;
48004690

48014691
// Get the oldest key
48024692
if (setKeyPool.empty())
@@ -4818,39 +4708,20 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fIn
48184708

48194709
assert(keypool.vchPubKey.IsValid());
48204710
LogPrintf("keypool reserve %d\n", nIndex);
4821-
}
4822-
}
4823-
4824-
void CWallet::ReserveEdKeyFromKeyPool(int64_t& nIndex, CEdKeyPool& edkeypool, bool fInternal)
4825-
{
4826-
nIndex = -1;
4827-
{
4828-
LOCK(cs_wallet);
4829-
4830-
if (!IsLocked(true))
4831-
TopUpKeyPoolCombo(); //TopUpEdKeyPool();
4832-
4833-
fInternal = fInternal && IsHDEnabled();
4834-
std::set<int64_t>& setEdKeyPool = fInternal ? setInternalEdKeyPool : setExternalEdKeyPool;
48354711

4836-
// Get the oldest key
4837-
if (setEdKeyPool.empty())
4838-
return;
4839-
4840-
CWalletDB walletdb(strWalletFile);
4841-
4842-
nIndex = *setEdKeyPool.begin();
4843-
setEdKeyPool.erase(nIndex);
4844-
if (!walletdb.ReadEdPool(nIndex, edkeypool)) {
4712+
nEdIndex = *setEdKeyPool.begin();
4713+
setEdKeyPool.erase(nEdIndex);
4714+
if (!walletdb.ReadEdPool(nEdIndex, edkeypool)) {
48454715
throw std::runtime_error(std::string(__func__) + ": read failed");
48464716
}
48474717
if (edkeypool.fInternal != fInternal) {
48484718
throw std::runtime_error(std::string(__func__) + ": keypool entry misclassified");
48494719
}
48504720

4851-
LogPrintf("edkeypool reserve %d\n", nIndex);
4721+
LogPrintf("edkeypool reserve %d\n", nEdIndex);
4722+
48524723
}
4853-
} //ReserveEdKeyFromKeyPool
4724+
} //ReserveKeysFromKeyPools
48544725

48554726
void CWallet::ReserveEdKeyForTransactions(const std::vector<unsigned char>& pubKeyToReserve)
48564727
{
@@ -4872,7 +4743,6 @@ void CWallet::ReserveEdKeyForTransactions(const std::vector<unsigned char>& pubK
48724743

48734744
if(pubKeyToReserve == edPubKey) {
48744745
KeepKey(nIndex);
4875-
KeepEdKey(nIndex);
48764746
fNeedToUpdateKeyPools = true;
48774747
EraseIndex = true;
48784748
IndexToErase = nIndex;
@@ -4897,18 +4767,10 @@ void CWallet::KeepKey(int64_t nIndex)
48974767
if (fFileBacked) {
48984768
CWalletDB walletdb(strWalletFile);
48994769
walletdb.ErasePool(nIndex);
4770+
walletdb.EraseEdPool(nIndex);
49004771
nKeysLeftSinceAutoBackup = nWalletBackups ? nKeysLeftSinceAutoBackup - 1 : 0;
49014772
}
49024773
LogPrintf("keypool keep %d\n", nIndex);
4903-
}
4904-
4905-
void CWallet::KeepEdKey(int64_t nIndex)
4906-
{
4907-
// Remove from key pool
4908-
if (fFileBacked) {
4909-
CWalletDB walletdb(strWalletFile);
4910-
walletdb.EraseEdPool(nIndex);
4911-
}
49124774
LogPrintf("edkeypool keep %d\n", nIndex);
49134775
}
49144776

@@ -4919,11 +4781,14 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal)
49194781
LOCK(cs_wallet);
49204782
if (fInternal) {
49214783
setInternalKeyPool.insert(nIndex);
4784+
setInternalEdKeyPool.insert(nIndex);
49224785
} else {
49234786
setExternalKeyPool.insert(nIndex);
4787+
setExternalEdKeyPool.insert(nIndex);
49244788
}
49254789
}
49264790
LogPrintf("keypool return %d\n", nIndex);
4791+
LogPrintf("edkeypool return %d\n", nIndex);
49274792
}
49284793

49294794
bool CWallet::GetKeysFromPool(CPubKey& pubkeyWallet, std::vector<unsigned char>& vchEd25519PubKey, CStealthAddress& sxAddr, bool fInternal)
@@ -4952,17 +4817,19 @@ bool CWallet::GetKeysFromPool(CPubKey& pubkeyWallet, std::vector<unsigned char>&
49524817
int64_t nEdIndex = 0;
49534818
CKeyPool keypool;
49544819
CEdKeyPool edkeypool;
4820+
bool keptAlready = false;
49554821
{
49564822
LOCK(cs_wallet);
4957-
ReserveKeyFromKeyPool(nIndex, keypool, fInternal);
4958-
ReserveEdKeyFromKeyPool(nEdIndex, edkeypool, fInternal);
4823+
ReserveKeysFromKeyPools(nIndex, keypool, edkeypool, fInternal);
4824+
nEdIndex = nIndex;
49594825
if (nIndex == -1) {
49604826
if (IsLocked(true))
49614827
return false;
49624828
// TODO: implement keypool for all accouts?
49634829
pubkeyWallet = GenerateNewKey(0, fInternal);
49644830
}
49654831
else {
4832+
keptAlready = true;
49664833
KeepKey(nIndex);
49674834
pubkeyWallet = keypool.vchPubKey;
49684835
}
@@ -4976,7 +4843,8 @@ bool CWallet::GetKeysFromPool(CPubKey& pubkeyWallet, std::vector<unsigned char>&
49764843
vchEd25519PubKey = GenerateNewEdKey(0, fInternal, keyRetrieved);
49774844
}
49784845
else {
4979-
KeepEdKey(nEdIndex);
4846+
if (!keptAlready)
4847+
KeepKey(nIndex);
49804848
vchEd25519PubKey = edkeypool.edPubKey;
49814849
}
49824850
}
@@ -5183,7 +5051,8 @@ bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool fInternalIn)
51835051
{
51845052
if (nIndex == -1) {
51855053
CKeyPool keypool;
5186-
pwallet->ReserveKeyFromKeyPool(nIndex, keypool, fInternalIn);
5054+
CEdKeyPool edkeypool;
5055+
pwallet->ReserveKeysFromKeyPools(nIndex, keypool, edkeypool, fInternalIn);
51875056
if (nIndex != -1) {
51885057
vchPubKey = keypool.vchPubKey;
51895058
} else {

0 commit comments

Comments
 (0)