else
return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
}
+ return false;
}
bool CWallet::Unlock(const string& strWalletPassphrase)
if (!pwalletdbEncryption->TxnCommit())
exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet.
- pwalletdbEncryption->Close();
+ delete pwalletdbEncryption;
pwalletdbEncryption = NULL;
}
Lock();
+ Unlock(strWalletPassphrase);
+ NewKeyPool();
+ Lock();
+
+ // Need to completely rewrite the wallet file; if we don't, bdb might keep
+ // bits of the unencrypted private key in slack space in the database file.
+ CDB::Rewrite(strWalletFile);
}
return true;
{
if (txout.scriptPubKey == scriptDefaultKey)
{
- SetDefaultKey(GetOrReuseKeyFromPool());
- SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
+ std::vector<unsigned char> newDefaultKey;
+ if (GetKeyFromPool(newDefaultKey, false))
+ {
+ SetDefaultKey(newDefaultKey);
+ SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
+ }
}
}
int64 CWalletTx::GetTxTime() const
{
- CRITICAL_BLOCK(cs_main)
- {
- if (!fTimeReceivedIsTxTime && hashBlock != 0)
- {
- // If we did not receive the transaction directly, we rely on the block's
- // time to figure out when it happened. We use the median over a range
- // of blocks to try to filter out inaccurate block times.
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex)
- return pindex->GetMedianTime();
- }
- }
- }
return nTimeReceived;
}
{
map<uint256, const CMerkleTx*> mapWalletPrev;
set<uint256> setAlreadyDone;
- for (int i = 0; i < vWorkQueue.size(); i++)
+ for (unsigned int i = 0; i < vWorkQueue.size(); i++)
{
uint256 hash = vWorkQueue[i];
if (setAlreadyDone.count(hash))
vtxPrev.push_back(tx);
if (nDepth < COPY_DEPTH)
+ {
BOOST_FOREACH(const CTxIn& txin, tx.vin)
vWorkQueue.push_back(txin.prevout.hash);
+ }
}
}
}
printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
continue;
}
- for (int i = 0; i < txindex.vSpent.size(); i++)
+ for (unsigned int i = 0; i < txindex.vSpent.size(); i++)
{
if (wtx.IsSpent(i))
continue;
if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
continue;
- for (int i = 0; i < pcoin->vout.size(); i++)
+ for (unsigned int i = 0; i < pcoin->vout.size(); i++)
{
if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
continue;
if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
{
- for (int i = 0; i < vValue.size(); ++i)
+ for (unsigned int i = 0; i < vValue.size(); ++i)
{
setCoinsRet.insert(vValue[i].second);
nValueRet += vValue[i].first;
bool fReachedTarget = false;
for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
{
- for (int i = 0; i < vValue.size(); i++)
+ for (unsigned int i = 0; i < vValue.size(); i++)
{
if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
{
nValueRet += coinLowestLarger.first;
}
else {
- for (int i = 0; i < vValue.size(); i++)
+ for (unsigned int i = 0; i < vValue.size(); i++)
if (vfBest[i])
{
setCoinsRet.insert(vValue[i].second);
//// debug print
printf("SelectCoins() best subset: ");
- for (int i = 0; i < vValue.size(); i++)
+ for (unsigned int i = 0; i < vValue.size(); i++)
if (vfBest[i])
printf("%s ", FormatMoney(vValue[i].first).c_str());
printf("total %s\n", FormatMoney(nBest).c_str());
return false;
fFirstRunRet = false;
int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
+ if (nLoadWalletRet == DB_NEED_REWRITE)
+ {
+ if (CDB::Rewrite(strWalletFile, "\x04pool"))
+ {
+ setKeyPool.clear();
+ // Note: can't top-up keypool here, because wallet is locked.
+ // User will be prompted to unlock wallet the next operation
+ // the requires a new key.
+ }
+ nLoadWalletRet = DB_NEED_REWRITE;
+ }
+
if (nLoadWalletRet != DB_LOAD_OK)
return nLoadWalletRet;
fFirstRunRet = vchDefaultKey.empty();
// Create new keyUser and set as default key
RandAddSeedPerfmon();
- SetDefaultKey(GetOrReuseKeyFromPool());
+ std::vector<unsigned char> newDefaultKey;
+ if (!GetKeyFromPool(newDefaultKey, false))
+ return DB_LOAD_FAIL;
+ SetDefaultKey(newDefaultKey);
if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
return DB_LOAD_FAIL;
}
return true;
}
+//
+// Mark old keypool keys as used,
+// and generate all new keys
+//
+bool CWallet::NewKeyPool()
+{
+ CRITICAL_BLOCK(cs_wallet)
+ {
+ CWalletDB walletdb(strWalletFile);
+ BOOST_FOREACH(int64 nIndex, setKeyPool)
+ walletdb.ErasePool(nIndex);
+ setKeyPool.clear();
+
+ if (IsLocked())
+ return false;
+
+ int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
+ for (int i = 0; i < nKeys; i++)
+ {
+ int64 nIndex = i+1;
+ walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
+ setKeyPool.insert(nIndex);
+ }
+ printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
+ }
+ return true;
+}
+
bool CWallet::TopUpKeyPool()
{
CRITICAL_BLOCK(cs_wallet)
printf("keypool return %"PRI64d"\n", nIndex);
}
-vector<unsigned char> CWallet::GetOrReuseKeyFromPool()
+bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
{
int64 nIndex = 0;
CKeyPool keypool;
- ReserveKeyFromKeyPool(nIndex, keypool);
- if(nIndex == -1)
- return vchDefaultKey;
- KeepKey(nIndex);
- return keypool.vchPubKey;
+ CRITICAL_BLOCK(cs_wallet)
+ {
+ ReserveKeyFromKeyPool(nIndex, keypool);
+ if (nIndex == -1)
+ {
+ 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()