Merge pull request #467 from gavinandresen/keypoolzero

Logic running with -keypool=0 was wrong (empty keys were being returned).
This commit is contained in:
Gavin Andresen 2011-09-01 12:01:29 -07:00
commit 783c636c73
5 changed files with 48 additions and 28 deletions

View file

@ -2183,7 +2183,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Keep giving the same key to the same ip until they use it // Keep giving the same key to the same ip until they use it
if (!mapReuseKey.count(pfrom->addr.ip)) if (!mapReuseKey.count(pfrom->addr.ip))
mapReuseKey[pfrom->addr.ip] = pwalletMain->GetOrReuseKeyFromPool(); pwalletMain->GetKeyFromPool(mapReuseKey[pfrom->addr.ip], true);
// Send back approval of order and pubkey to use // Send back approval of order and pubkey to use
CScript scriptPubKey; CScript scriptPubKey;

View file

@ -331,21 +331,20 @@ Value getnewaddress(const Array& params, bool fHelp)
"If [account] is specified (recommended), it is added to the address book " "If [account] is specified (recommended), it is added to the address book "
"so payments received with the address will be credited to [account]."); "so payments received with the address will be credited to [account].");
if (!pwalletMain->IsLocked())
pwalletMain->TopUpKeyPool();
if (pwalletMain->GetKeyPoolSize() < 1)
throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
// Parse the account first so we don't generate a key if there's an error // Parse the account first so we don't generate a key if there's an error
string strAccount; string strAccount;
if (params.size() > 0) if (params.size() > 0)
strAccount = AccountFromValue(params[0]); strAccount = AccountFromValue(params[0]);
// Generate a new key that is added to wallet if (!pwalletMain->IsLocked())
CBitcoinAddress address(pwalletMain->GetOrReuseKeyFromPool()); pwalletMain->TopUpKeyPool();
// Generate a new key that is added to wallet
std::vector<unsigned char> newKey;
if (!pwalletMain->GetKeyFromPool(newKey, false))
throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
CBitcoinAddress address(newKey);
// This could be done in the same main CS as GetKeyFromKeyPool.
pwalletMain->SetAddressBookName(address, strAccount); pwalletMain->SetAddressBookName(address, strAccount);
return address.ToString(); return address.ToString();
@ -382,12 +381,9 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
{ {
if (pwalletMain->GetKeyPoolSize() < 1) if (pwalletMain->GetKeyPoolSize() < 1)
{ {
if (bKeyUsed || bForceNew) if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first"); throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
}
else
{
account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount); pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
walletdb.WriteAccount(strAccount, account); walletdb.WriteAccount(strAccount, account);
} }

View file

@ -1391,7 +1391,9 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
return; return;
// Generate new key // Generate new key
strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString(); std::vector<unsigned char> newKey;
pwalletMain->GetKeyFromPool(newKey, true);
strAddress = CBitcoinAddress(newKey).ToString();
if (fWasLocked) if (fWasLocked)
pwalletMain->Lock(); pwalletMain->Lock();
@ -2826,7 +2828,9 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
return; return;
// Generate new key // Generate new key
strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString(); std::vector<unsigned char> newKey;
pwalletMain->GetKeyFromPool(newKey, true);
strAddress = CBitcoinAddress(newKey).ToString();
if (fWasLocked) if (fWasLocked)
pwalletMain->Lock(); pwalletMain->Lock();

View file

@ -268,8 +268,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
{ {
if (txout.scriptPubKey == scriptDefaultKey) if (txout.scriptPubKey == scriptDefaultKey)
{ {
SetDefaultKey(GetOrReuseKeyFromPool()); std::vector<unsigned char> newDefaultKey;
SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""); if (GetKeyFromPool(newDefaultKey, false))
{
SetDefaultKey(newDefaultKey);
SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
}
} }
} }
@ -1126,7 +1130,10 @@ int CWallet::LoadWallet(bool& fFirstRunRet)
// Create new keyUser and set as default key // Create new keyUser and set as default key
RandAddSeedPerfmon(); RandAddSeedPerfmon();
SetDefaultKey(GetOrReuseKeyFromPool()); std::vector<unsigned char> newDefaultKey;
if (!GetKeyFromPool(newDefaultKey, false))
return DB_LOAD_FAIL;
SetDefaultKey(newDefaultKey);
if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), "")) if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
return DB_LOAD_FAIL; return DB_LOAD_FAIL;
} }
@ -1269,15 +1276,28 @@ void CWallet::ReturnKey(int64 nIndex)
printf("keypool return %"PRI64d"\n", nIndex); printf("keypool return %"PRI64d"\n", nIndex);
} }
vector<unsigned char> CWallet::GetOrReuseKeyFromPool() bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
{ {
int64 nIndex = 0; int64 nIndex = 0;
CKeyPool keypool; CKeyPool keypool;
ReserveKeyFromKeyPool(nIndex, keypool); CRITICAL_BLOCK(cs_wallet)
if(nIndex == -1) {
return vchDefaultKey; ReserveKeyFromKeyPool(nIndex, keypool);
KeepKey(nIndex); if (nIndex == -1)
return keypool.vchPubKey; {
if (fAllowReuse && !vchDefaultKey.empty())
{
result = vchDefaultKey;
return true;
}
if (IsLocked()) return false;
result = GenerateNewKey();
return true;
}
KeepKey(nIndex);
result = keypool.vchPubKey;
}
return true;
} }
int64 CWallet::GetOldestKeyPoolTime() int64 CWallet::GetOldestKeyPoolTime()

View file

@ -85,7 +85,7 @@ public:
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool); void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
void KeepKey(int64 nIndex); void KeepKey(int64 nIndex);
void ReturnKey(int64 nIndex); void ReturnKey(int64 nIndex);
std::vector<unsigned char> GetOrReuseKeyFromPool(); bool GetKeyFromPool(std::vector<unsigned char> &key, bool fAllowReuse=true);
int64 GetOldestKeyPoolTime(); int64 GetOldestKeyPoolTime();
bool IsMine(const CTxIn& txin) const; bool IsMine(const CTxIn& txin) const;