X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fwallet.cpp;h=88d661e1fb39de14f0d5bc560a0651f0aaee1150;hb=24c742a46d44c8f10a2a94d1bd5227e8a0ae30ed;hp=3906f27850aea82133d55bb1c6d2ba96d51a73a1;hpb=c8a7f72c867da909f4a4dd1d1e1c028ba8547590;p=novacoin.git diff --git a/src/wallet.cpp b/src/wallet.cpp index 3906f27..88d661e 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -62,7 +62,6 @@ CPubKey CWallet::GenerateNewKey() bool CWallet::AddKey(const CKey& key) { CPubKey pubkey = key.GetPubKey(); - if (!CCryptoKeyStore::AddKey(key)) return false; if (!fFileBacked) @@ -268,13 +267,6 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, if (fFileBacked) { CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile); - if (nWalletVersion >= 40000) - { - // Versions prior to 0.4.0 did not support the "minversion" record. - // Use a CCorruptAddress to make them crash instead. - CCorruptAddress corruptAddress; - pwalletdb->WriteSetting("addrIncoming", corruptAddress); - } if (nWalletVersion > 40000) pwalletdb->WriteMinVersion(nWalletVersion); if (!pwalletdbIn) @@ -306,7 +298,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE); RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE); - CMasterKey kMasterKey(nDerivationMethodIndex); + CMasterKey kMasterKey; RandAddSeedPerfmon(); kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE); @@ -376,6 +368,77 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) return true; } +bool CWallet::DecryptWallet(const SecureString& strWalletPassphrase) +{ + if (!IsCrypted()) + return false; + + CCrypter crypter; + CKeyingMaterial vMasterKey; + + { + LOCK(cs_wallet); + BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) + { + if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) + return false; + if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) + return false; + if (!CCryptoKeyStore::Unlock(vMasterKey)) + return false; + } + + if (fFileBacked) + { + pwalletdbDecryption = new CWalletDB(strWalletFile); + if (!pwalletdbDecryption->TxnBegin()) + return false; + } + + if (!DecryptKeys(vMasterKey)) + { + if (fFileBacked) + pwalletdbDecryption->TxnAbort(); + exit(1); //We now probably have half of our keys decrypted in memory, and half not...die and let the user reload their encrypted wallet. + } + + if (fFileBacked) + { + // Overwrite crypted keys + KeyMap::const_iterator mi = mapKeys.begin(); + while (mi != mapKeys.end()) + { + CKey key; + key.SetSecret((*mi).second.first, (*mi).second.second); + pwalletdbDecryption->EraseCryptedKey(key.GetPubKey()); + pwalletdbDecryption->WriteKey(key.GetPubKey(), key.GetPrivKey(), mapKeyMetadata[(*mi).first]); + mi++; + } + + // Erase master keys + MasterKeyMap::const_iterator mk = mapMasterKeys.begin(); + while (mk != mapMasterKeys.end()) + { + pwalletdbDecryption->EraseMasterKey((*mk).first); + mk++; + } + + if (!pwalletdbDecryption->TxnCommit()) + exit(1); //We now have keys decrypted in memory, but no on disk...die to avoid confusion and let the user reload their encrypted wallet. + + delete pwalletdbDecryption; + pwalletdbDecryption = NULL; + } + + // Need to completely rewrite the wallet file; if we don't, bdb might keep + // encrypted private keys in the database file which can be a reason of consistency issues. + CDB::Rewrite(strWalletFile); + } + NotifyStatusChanged(this); + + return true; +} + int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) { int64_t nRet = nOrderPosNext++; @@ -1018,7 +1081,7 @@ void CWallet::ResendWalletTransactions() { // Do this infrequently and randomly to avoid giving away // that these are our transactions. - static int64_t nNextTime; + static int64_t nNextTime = GetRand(GetTime() + 30 * 60); if (GetTime() < nNextTime) return; bool fFirst = (nNextTime == 0); @@ -1027,7 +1090,7 @@ void CWallet::ResendWalletTransactions() return; // Only do it if there's been a new block since last time - static int64_t nLastTime; + static int64_t nLastTime = 0; if (nTimeBestReceived < nLastTime) return; nLastTime = GetTime(); @@ -1794,7 +1857,7 @@ bool CWallet::MergeCoins(const int64_t& nAmount, const int64_t& nMinValue, const } -bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64_t nSearchInterval, CTransaction& txNew, CKey& key) +bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, uint32_t nSearchInterval, CTransaction& txNew, CKey& key) { // The following combine threshold is important to security // Should not be adjusted if you don't understand the consequences @@ -1876,18 +1939,11 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int int64_t nCredit = 0; CScript scriptPubKeyKernel; - KernelSearchSettings settings; - settings.nBits = nBits; - settings.nTime = txNew.nTime; - settings.nOffset = 0; - settings.nLimit = mapMeta.size(); - settings.nSearchInterval = nSearchInterval; - unsigned int nTimeTx, nBlockTime; COutPoint prevoutStake; CoinsSet::value_type kernelcoin; - if (ScanForStakeKernelHash(mapMeta, settings, kernelcoin, nTimeTx, nBlockTime, nKernelsTried, nCoinDaysTried)) + if (ScanForStakeKernelHash(mapMeta, nBits, txNew.nTime, nSearchInterval, kernelcoin, nTimeTx, nBlockTime, nKernelsTried, nCoinDaysTried)) { // Found a kernel if (fDebug && GetBoolArg("-printcoinstake")) @@ -2053,9 +2109,24 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) { { - LOCK2(cs_main, cs_wallet); printf("CommitTransaction:\n%s", wtxNew.ToString().c_str()); + + // Track how many getdata requests our transaction gets + mapRequestCount[wtxNew.GetHash()] = 0; + + // Try to broadcast before saving + if (!wtxNew.AcceptToMemoryPool()) { + // This must not fail. The transaction has already been signed. + printf("CommitTransaction() : Error: Transaction not valid"); + return false; + } + + wtxNew.RelayWalletTransaction(); + + { + LOCK2(cs_main, cs_wallet); + // This is only to keep the database open to defeat the auto-flush for the // duration of this scope. This is the only place where this optimization // maybe makes sense; please don't do it anywhere else. @@ -2083,18 +2154,6 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) if (fFileBacked) delete pwalletdb; } - - // Track how many getdata requests our transaction gets - mapRequestCount[wtxNew.GetHash()] = 0; - - // Broadcast - if (!wtxNew.AcceptToMemoryPool()) - { - // This must not fail. The transaction has already been signed and recorded. - printf("CommitTransaction() : Error: Transaction not valid"); - return false; - } - wtxNew.RelayWalletTransaction(); } return true; } @@ -2184,6 +2243,28 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) return DB_LOAD_OK; } +DBErrors CWallet::ZapWalletTx() +{ + if (!fFileBacked) + return DB_LOAD_OK; + DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this); + if (nZapWalletTxRet == DB_NEED_REWRITE) + { + if (CDB::Rewrite(strWalletFile, "\x04pool")) + { + LOCK(cs_wallet); + 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. + } + } + + if (nZapWalletTxRet != DB_LOAD_OK) + return nZapWalletTxRet; + + return DB_LOAD_OK; +} bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName) { @@ -2260,7 +2341,7 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut) // Mark old keypool keys as used, // and generate all new keys // -bool CWallet::NewKeyPool() +bool CWallet::NewKeyPool(unsigned int nSize) { { LOCK(cs_wallet); @@ -2272,14 +2353,19 @@ bool CWallet::NewKeyPool() if (IsLocked()) return false; - int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0); - for (int i = 0; i < nKeys; i++) + uint64_t nKeys; + if (nSize > 0) + nKeys = nSize; + else + nKeys = max(GetArg("-keypool", 100), 0); + + for (uint64_t i = 0; i < nKeys; i++) { - int64_t nIndex = i+1; + uint64_t nIndex = i+1; walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey())); setKeyPool.insert(nIndex); } - printf("CWallet::NewKeyPool wrote %" PRId64 " new keys\n", nKeys); + printf("CWallet::NewKeyPool wrote %" PRIu64 " new keys\n", nKeys); } return true; } @@ -2295,21 +2381,21 @@ bool CWallet::TopUpKeyPool(unsigned int nSize) CWalletDB walletdb(strWalletFile); // Top up key pool - unsigned int nTargetSize; + uint64_t nTargetSize; if (nSize > 0) nTargetSize = nSize; else - nTargetSize = max(GetArg("-keypool", 100), 0LL); + nTargetSize = max(GetArg("-keypool", 100), 0); while (setKeyPool.size() < (nTargetSize + 1)) { - int64_t nEnd = 1; + uint64_t nEnd = 1; if (!setKeyPool.empty()) nEnd = *(--setKeyPool.end()) + 1; if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey()))) throw runtime_error("TopUpKeyPool() : writing generated key failed"); setKeyPool.insert(nEnd); - printf("keypool added key %" PRId64 ", size=%" PRIszu "\n", nEnd, setKeyPool.size()); + printf("keypool added key %" PRIu64 ", size=%" PRIszu "\n", nEnd, setKeyPool.size()); } } return true;