X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fwallet.cpp;h=5976cb544d308e11d14329fda809382a33189d08;hb=989736e823e0841ce4ba4ac21554ba6426f3f4a4;hp=12000bee2c2d5b374d08297b53e0a4d55db625f9;hpb=ae803b031b600e073edf8507ab943580672f93c4;p=novacoin.git diff --git a/src/wallet.cpp b/src/wallet.cpp index 12000be..5976cb5 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -94,12 +94,32 @@ bool CWallet::AddKey(const CKey& key) bool CWallet::AddMalleableKey(const CMalleableKey& mKey) { CMalleableKeyView keyView = CMalleableKeyView(mKey); - if (!CCryptoKeyStore::AddMalleableKey(mKey)) + CSecret vchSecretH = mKey.GetSecretH(); + if (!CCryptoKeyStore::AddMalleableKey(keyView, vchSecretH)) return false; if (!fFileBacked) return true; if (!IsCrypted()) - return CWalletDB(strWalletFile).WriteMalleableKey(keyView, mKey, mapMalleableKeyMetadata[keyView]); + return CWalletDB(strWalletFile).WriteMalleableKey(keyView, vchSecretH, mapMalleableKeyMetadata[keyView]); + return true; +} + +bool CWallet::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector &vchCryptedSecretH) +{ + if (!CCryptoKeyStore::AddCryptedMalleableKey(keyView, vchCryptedSecretH)) + return false; + + if (!fFileBacked) + return true; + + { + LOCK(cs_wallet); + if (pwalletdbEncryption) + return pwalletdbEncryption->WriteCryptedMalleableKey(keyView, vchCryptedSecretH, mapMalleableKeyMetadata[keyView]); + else + return CWalletDB(strWalletFile).WriteCryptedMalleableKey(keyView, vchCryptedSecretH, mapMalleableKeyMetadata[keyView]); + } + return true; } @@ -460,6 +480,16 @@ bool CWallet::DecryptWallet(const SecureString& strWalletPassphrase) mi++; } + MalleableKeyMap::const_iterator mi2 = mapMalleableKeys.begin(); + while (mi2 != mapMalleableKeys.end()) + { + const CSecret &vchSecretH = mi2->second; + const CMalleableKeyView &keyView = mi2->first; + pwalletdbDecryption->EraseCryptedMalleableKey(keyView); + pwalletdbDecryption->WriteMalleableKey(keyView, vchSecretH, mapMalleableKeyMetadata[keyView]); + mi2++; + } + // Erase master keys MasterKeyMap::const_iterator mk = mapMasterKeys.begin(); while (mk != mapMasterKeys.end()) @@ -1658,8 +1688,8 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CScript scriptChange; // coin control: send change to custom address - if (coinControl && !boost::get(&coinControl->destChange)) - scriptChange.SetDestination(coinControl->destChange); + if (coinControl && coinControl->destChange.IsValid()) + scriptChange.SetAddress(coinControl->destChange); // no coin control: send change to newly generated address else @@ -2711,55 +2741,50 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx) } } -void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) const { - mapKeyBirth.clear(); +void CWallet::GetAddresses(std::map &mapAddresses) const { + mapAddresses.clear(); // get birth times for keys with metadata - for (std::map::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++) - if (it->second.nCreateTime) - mapKeyBirth[it->first] = it->second.nCreateTime; - - // map in which we'll infer heights of other keys - CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin - std::map mapKeyFirstBlock; - std::set setKeys; - GetKeys(setKeys); - BOOST_FOREACH(const CKeyID &keyid, setKeys) { - if (mapKeyBirth.count(keyid) == 0) - mapKeyFirstBlock[keyid] = pindexMax; - } - setKeys.clear(); - - // if there are no such keys, we're done - if (mapKeyFirstBlock.empty()) - return; + for (std::map::const_iterator it = mapMalleableKeyMetadata.begin(); it != mapMalleableKeyMetadata.end(); it++) { + CBitcoinAddress addr(it->first.GetMalleablePubKey()); + mapAddresses[addr] = it->second.nCreateTime ? it->second.nCreateTime : 0; + } + + for (std::map::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++) { + CBitcoinAddress addr(it->first); + mapAddresses[addr] = it->second.nCreateTime ? it->second.nCreateTime : 0; + } - // find first block that affects those keys, if there are any left - std::vector vAffected; for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) { // iterate over all wallet transactions... const CWalletTx &wtx = (*it).second; - std::map::const_iterator blit = mapBlockIndex.find(wtx.hashBlock); - if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) { - // ... which are already in a block - int nHeight = blit->second->nHeight; - BOOST_FOREACH(const CTxOut &txout, wtx.vout) { - // iterate over all their outputs - ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected); - BOOST_FOREACH(const CKeyID &keyid, vAffected) { - // ... and all their affected keys - std::map::iterator rit = mapKeyFirstBlock.find(keyid); - if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight) - rit->second = blit->second; + if (wtx.hashBlock == 0) + continue; // skip unconfirmed transactions + + for(std::vector::const_iterator it2 = wtx.vout.begin(); it2 != wtx.vout.end(); it2++) { + const CTxOut &out = (*it2); + // iterate over all their outputs + CBitcoinAddress addressRet; + if (const_cast(this)->ExtractAddress(out.scriptPubKey, addressRet)) { + if (mapAddresses.find(addressRet) != mapAddresses.end() && (mapAddresses[addressRet] == 0 || mapAddresses[addressRet] > wtx.nTime)) + mapAddresses[addressRet] = wtx.nTime; + } + else { + // multisig output affects more than one key + std::vector vAffected; + ::ExtractAffectedKeys(*this, out.scriptPubKey, vAffected); + + for(std::vector::const_iterator it3 = vAffected.begin(); it3 != vAffected.end(); it3++) { + CBitcoinAddress addrAffected(*it3); + + if (mapAddresses.find(addrAffected) != mapAddresses.end() && (mapAddresses[addrAffected] == 0 || mapAddresses[addrAffected] > wtx.nTime)) + mapAddresses[addrAffected] = wtx.nTime; } vAffected.clear(); } } - } - // Extract block timestamps for those keys - for (std::map::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++) - mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off + } } void CWallet::ClearOrphans() @@ -2779,3 +2804,39 @@ void CWallet::ClearOrphans() for(list::const_iterator it = orphans.begin(); it != orphans.end(); ++it) EraseFromWallet(*it); } + +bool CWallet::ExtractAddress(const CScript& scriptPubKey, CBitcoinAddress& addressRet) +{ + vector vSolutions; + txnouttype whichType; + if (!Solver(scriptPubKey, whichType, vSolutions)) + return false; + + if (whichType == TX_PUBKEY) + { + addressRet = CBitcoinAddress(CPubKey(vSolutions[0]).GetID()); + return true; + } + if (whichType == TX_PUBKEY_DROP) + { + // Pay-to-Pubkey-R + CMalleableKeyView view; + if (!CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view)) + return false; + + addressRet = CBitcoinAddress(view.GetMalleablePubKey()); + return true; + } + else if (whichType == TX_PUBKEYHASH) + { + addressRet = CBitcoinAddress(CKeyID(uint160(vSolutions[0]))); + return true; + } + else if (whichType == TX_SCRIPTHASH) + { + addressRet = CBitcoinAddress(CScriptID(uint160(vSolutions[0]))); + return true; + } + // Multisig txns have more than one address... + return false; +}