Browse Source

get rid of mapPubKeys

Make CKeyStore's interface work on uint160's instead of pubkeys, so
no separate global mapPubKeys is necessary anymore.
metaverse
Pieter Wuille 13 years ago
parent
commit
03fbd79049
  1. 1
      src/init.cpp
  2. 58
      src/keystore.cpp
  3. 30
      src/keystore.h
  4. 3
      src/main.cpp
  5. 2
      src/main.h
  6. 6
      src/rpc.cpp
  7. 64
      src/script.cpp
  8. 3
      src/script.h
  9. 25
      src/ui.cpp
  10. 9
      src/wallet.cpp
  11. 6
      src/wallet.h

1
src/init.cpp

@ -425,7 +425,6 @@ bool AppInit2(int argc, char* argv[])
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
printf("nBestHeight = %d\n", nBestHeight);
printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
printf("mapPubKeys.size() = %d\n", mapPubKeys.size());
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());

58
src/keystore.cpp

@ -16,14 +16,19 @@ std::vector<unsigned char> CKeyStore::GenerateNewKey()
return key.GetPubKey();
}
bool CKeyStore::GetPubKey(const uint160 &hashAddress, std::vector<unsigned char> &vchPubKeyOut) const
{
CKey key;
if (!GetKey(hashAddress, key))
return false;
vchPubKeyOut = key.GetPubKey();
return true;
}
bool CBasicKeyStore::AddKey(const CKey& key)
{
CRITICAL_BLOCK(cs_mapPubKeys)
CRITICAL_BLOCK(cs_KeyStore)
{
mapKeys[key.GetPubKey()] = key.GetPrivKey();
mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
}
mapKeys[Hash160(key.GetPubKey())] = key.GetSecret();
return true;
}
@ -44,11 +49,11 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
if (!SetCrypted())
return false;
std::map<std::vector<unsigned char>, std::vector<unsigned char> >::const_iterator mi = mapCryptedKeys.begin();
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
for (; mi != mapCryptedKeys.end(); ++mi)
{
const std::vector<unsigned char> &vchPubKey = (*mi).first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second;
const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
CSecret vchSecret;
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
return false;
@ -88,31 +93,30 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
CRITICAL_BLOCK(cs_mapPubKeys)
CRITICAL_BLOCK(cs_KeyStore)
{
if (!SetCrypted())
return false;
mapCryptedKeys[vchPubKey] = vchCryptedSecret;
mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
mapCryptedKeys[Hash160(vchPubKey)] = make_pair(vchPubKey, vchCryptedSecret);
}
return true;
}
bool CCryptoKeyStore::GetPrivKey(const std::vector<unsigned char> &vchPubKey, CKey& keyOut) const
bool CCryptoKeyStore::GetKey(const uint160 &hashAddress, CKey& keyOut) const
{
CRITICAL_BLOCK(cs_vMasterKey)
{
if (!IsCrypted())
return CBasicKeyStore::GetPrivKey(vchPubKey, keyOut);
return CBasicKeyStore::GetKey(hashAddress, keyOut);
std::map<std::vector<unsigned char>, std::vector<unsigned char> >::const_iterator mi = mapCryptedKeys.find(vchPubKey);
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(hashAddress);
if (mi != mapCryptedKeys.end())
{
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second;
const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
CSecret vchSecret;
if (!DecryptSecret(vMasterKey, (*mi).second, Hash((*mi).first.begin(), (*mi).first.end()), vchSecret))
if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
return false;
keyOut.SetSecret(vchSecret);
return true;
@ -121,6 +125,23 @@ bool CCryptoKeyStore::GetPrivKey(const std::vector<unsigned char> &vchPubKey, CK
return false;
}
bool CCryptoKeyStore::GetPubKey(const uint160 &hashAddress, std::vector<unsigned char>& vchPubKeyOut) const
{
CRITICAL_BLOCK(cs_vMasterKey)
{
if (!IsCrypted())
return CKeyStore::GetPubKey(hashAddress, vchPubKeyOut);
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(hashAddress);
if (mi != mapCryptedKeys.end())
{
vchPubKeyOut = (*mi).second.first;
return true;
}
}
return false;
}
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
{
CRITICAL_BLOCK(cs_KeyStore)
@ -135,10 +156,11 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
{
if (!key.SetPrivKey(mKey.second))
return false;
const std::vector<unsigned char> vchPubKey = key.GetPubKey();
std::vector<unsigned char> vchCryptedSecret;
if (!EncryptSecret(vMasterKeyIn, key.GetSecret(), Hash(mKey.first.begin(), mKey.first.end()), vchCryptedSecret))
if (!EncryptSecret(vMasterKeyIn, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
return false;
if (!AddCryptedKey(mKey.first, vchCryptedSecret))
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
return false;
}
mapKeys.clear();

30
src/keystore.h

@ -12,12 +12,13 @@ public:
mutable CCriticalSection cs_KeyStore;
virtual bool AddKey(const CKey& key) =0;
virtual bool HaveKey(const std::vector<unsigned char> &vchPubKey) const =0;
virtual bool GetPrivKey(const std::vector<unsigned char> &vchPubKey, CKey& keyOut) const =0;
virtual bool HaveKey(const uint160 &hashAddress) const =0;
virtual bool GetKey(const uint160 &hashAddress, CKey& keyOut) const =0;
virtual bool GetPubKey(const uint160 &hashAddress, std::vector<unsigned char>& vchPubKeyOut) const;
virtual std::vector<unsigned char> GenerateNewKey();
};
typedef std::map<std::vector<unsigned char>, CPrivKey> KeyMap;
typedef std::map<uint160, CSecret> KeyMap;
class CBasicKeyStore : public CKeyStore
{
@ -26,26 +27,28 @@ protected:
public:
bool AddKey(const CKey& key);
bool HaveKey(const std::vector<unsigned char> &vchPubKey) const
bool HaveKey(const uint160 &hashAddress) const
{
return (mapKeys.count(vchPubKey) > 0);
return (mapKeys.count(hashAddress) > 0);
}
bool GetPrivKey(const std::vector<unsigned char> &vchPubKey, CKey& keyOut) const
bool GetKey(const uint160 &hashAddress, CKey& keyOut) const
{
std::map<std::vector<unsigned char>, CPrivKey>::const_iterator mi = mapKeys.find(vchPubKey);
KeyMap::const_iterator mi = mapKeys.find(hashAddress);
if (mi != mapKeys.end())
{
keyOut.SetPrivKey((*mi).second);
keyOut.SetSecret((*mi).second);
return true;
}
return false;
}
};
typedef std::map<uint160, std::pair<std::vector<unsigned char>, std::vector<unsigned char> > > CryptedKeyMap;
class CCryptoKeyStore : public CBasicKeyStore
{
private:
std::map<std::vector<unsigned char>, std::vector<unsigned char> > mapCryptedKeys;
CryptedKeyMap mapCryptedKeys;
CKeyingMaterial vMasterKey;
@ -103,13 +106,14 @@ public:
virtual bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
std::vector<unsigned char> GenerateNewKey();
bool AddKey(const CKey& key);
bool HaveKey(const std::vector<unsigned char> &vchPubKey) const
bool HaveKey(const uint160 &hashAddress) const
{
if (!IsCrypted())
return CBasicKeyStore::HaveKey(vchPubKey);
return mapCryptedKeys.count(vchPubKey) > 0;
return CBasicKeyStore::HaveKey(hashAddress);
return mapCryptedKeys.count(hashAddress) > 0;
}
bool GetPrivKey(const std::vector<unsigned char> &vchPubKey, CKey& keyOut) const;
bool GetKey(const uint160 &hashAddress, CKey& keyOut) const;
bool GetPubKey(const uint160 &hashAddress, std::vector<unsigned char>& vchPubKeyOut) const;
};
#endif

3
src/main.cpp

@ -21,9 +21,6 @@ set<CWallet*> setpwalletRegistered;
CCriticalSection cs_main;
CCriticalSection cs_mapPubKeys;
map<uint160, vector<unsigned char> > mapPubKeys;
map<uint256, CTransaction> mapTransactions;
CCriticalSection cs_mapTransactions;
unsigned int nTransactionsUpdated = 0;

2
src/main.h

@ -1568,7 +1568,5 @@ public:
extern std::map<uint256, CTransaction> mapTransactions;
extern std::map<uint160, std::vector<unsigned char> > mapPubKeys;
extern CCriticalSection cs_mapPubKeys;
#endif

6
src/rpc.cpp

@ -967,7 +967,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
{
// Only counting our own bitcoin addresses and not ip addresses
uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();
if (hash160 == 0 || !mapPubKeys.count(hash160)) // IsMine
if (hash160 == 0 || !pwalletMain->HaveKey(hash160)) // IsMine
continue;
tallyitem& item = mapTally[hash160];
@ -1242,7 +1242,7 @@ Value listaccounts(const Array& params, bool fHelp)
{
BOOST_FOREACH(const PAIRTYPE(string, string)& entry, pwalletMain->mapAddressBook) {
uint160 hash160;
if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me
if(AddressToHash160(entry.first, hash160) && pwalletMain->HaveKey(hash160)) // This address belongs to me
mapAccountBalances[entry.second] = 0;
}
@ -1564,7 +1564,7 @@ Value validateaddress(const Array& params, bool fHelp)
// version of the address:
string currentAddress = Hash160ToAddress(hash160);
ret.push_back(Pair("address", currentAddress));
ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0)));
ret.push_back(Pair("ismine", (pwalletMain->HaveKey(hash160) > 0)));
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
if (pwalletMain->mapAddressBook.count(currentAddress))

64
src/script.cpp

@ -1041,7 +1041,9 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
// Sign
const valtype& vchPubKey = item.second;
CKey key;
if (!keystore.GetPrivKey(vchPubKey, key))
if (!keystore.GetKey(Hash160(vchPubKey), key))
return false;
if (key.GetPubKey() != vchPubKey)
return false;
if (hash != 0)
{
@ -1055,12 +1057,8 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
else if (item.first == OP_PUBKEYHASH)
{
// Sign and give pubkey
map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
if (mi == mapPubKeys.end())
return false;
const vector<unsigned char>& vchPubKey = (*mi).second;
CKey key;
if (!keystore.GetPrivKey(vchPubKey, key))
if (!keystore.GetKey(uint160(item.second), key))
return false;
if (hash != 0)
{
@ -1068,7 +1066,7 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
if (!key.Sign(hash, vchSig))
return false;
vchSig.push_back((unsigned char)nHashType);
scriptSigRet << vchSig << vchPubKey;
scriptSigRet << vchSig << key.GetPubKey();
}
}
else
@ -1102,19 +1100,16 @@ bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
{
if (item.first == OP_PUBKEY)
{
// Sign
const valtype& vchPubKey = item.second;
if (!keystore.HaveKey(vchPubKey))
vector<unsigned char> vchPubKeyFound;
if (!keystore.GetPubKey(Hash160(vchPubKey), vchPubKeyFound))
return false;
if (vchPubKeyFound != vchPubKey)
return false;
}
else if (item.first == OP_PUBKEYHASH)
{
// Sign and give pubkey
map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
if (mi == mapPubKeys.end())
return false;
const vector<unsigned char>& vchPubKey = (*mi).second;
if (!keystore.HaveKey(vchPubKey))
if (!keystore.HaveKey(uint160(item.second)))
return false;
}
else
@ -1128,33 +1123,28 @@ bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
}
bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* keystore, vector<unsigned char>& vchPubKeyRet)
bool ExtractHash160(const CScript& scriptPubKey, const CKeyStore* keystore, uint160& hash160Ret)
{
vchPubKeyRet.clear();
vector<pair<opcodetype, valtype> > vSolution;
if (!Solver(scriptPubKey, vSolution))
return false;
CRITICAL_BLOCK(cs_mapPubKeys)
CRITICAL_BLOCK(keystore->cs_KeyStore)
{
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
valtype vchPubKey;
uint160 hash160;
if (item.first == OP_PUBKEY)
{
vchPubKey = item.second;
hash160 = Hash160(item.second);
}
else if (item.first == OP_PUBKEYHASH)
{
map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
if (mi == mapPubKeys.end())
continue;
vchPubKey = (*mi).second;
hash160 = uint160(item.second);
}
if (keystore == NULL || keystore->HaveKey(vchPubKey))
if (keystore == NULL || keystore->HaveKey(hash160))
{
vchPubKeyRet = vchPubKey;
hash160Ret = hash160;
return true;
}
}
@ -1163,26 +1153,6 @@ bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* keystore, vecto
}
bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret)
{
hash160Ret = 0;
vector<pair<opcodetype, valtype> > vSolution;
if (!Solver(scriptPubKey, vSolution))
return false;
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
if (item.first == OP_PUBKEYHASH)
{
hash160Ret = uint160(item.second);
return true;
}
}
return false;
}
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
vector<vector<unsigned char> > stack;

3
src/script.h

@ -710,8 +710,7 @@ public:
bool IsStandard(const CScript& scriptPubKey);
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
bool ExtractPubKey(const CScript& scriptPubKey, const CKeyStore* pkeystore, std::vector<unsigned char>& vchPubKeyRet);
bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret);
bool ExtractHash160(const CScript& scriptPubKey, const CKeyStore* pkeystore, uint160& hash160Ret);
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0);

25
src/ui.cpp

@ -238,9 +238,10 @@ void SetDefaultReceivingAddress(const string& strAddress)
uint160 hash160;
if (!AddressToHash160(strAddress, hash160))
return;
if (!mapPubKeys.count(hash160))
vector<unsigned char> vchPubKey;
if (!pwalletMain->GetPubKey(hash160, vchPubKey))
return;
pwalletMain->SetDefaultKey(mapPubKeys[hash160]);
pwalletMain->SetDefaultKey(vchPubKey);
pframeMain->m_textCtrlAddress->SetValue(strAddress);
}
}
@ -703,15 +704,15 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
{
if (pwalletMain->IsMine(txout))
{
vector<unsigned char> vchPubKey;
if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
uint160 hash160;
if (ExtractHash160(txout.scriptPubKey, pwalletMain, hash160))
{
CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
{
//strDescription += _("Received payment to ");
//strDescription += _("Received with address ");
strDescription += _("Received with: ");
string strAddress = PubKeyToAddress(vchPubKey);
string strAddress = Hash160ToAddress(hash160);
map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
{
@ -786,7 +787,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
{
// Sent to Bitcoin Address
uint160 hash160;
if (ExtractHash160(txout.scriptPubKey, hash160))
if (ExtractHash160(txout.scriptPubKey, pwalletMain, hash160))
strAddress = Hash160ToAddress(hash160);
}
@ -1502,10 +1503,10 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
{
if (pwalletMain->IsMine(txout))
{
vector<unsigned char> vchPubKey;
if (ExtractPubKey(txout.scriptPubKey, pwalletMain, vchPubKey))
uint160 hash160;
if (ExtractHash160(txout.scriptPubKey, pwalletMain, hash160))
{
string strAddress = PubKeyToAddress(vchPubKey);
string strAddress = Hash160ToAddress(hash160);
if (pwalletMain->mapAddressBook.count(strAddress))
{
strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>";
@ -1589,7 +1590,7 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
{
// Offline transaction
uint160 hash160;
if (ExtractHash160(txout.scriptPubKey, hash160))
if (ExtractHash160(txout.scriptPubKey, pwalletMain, hash160))
{
string strAddress = Hash160ToAddress(hash160);
strHTML += _("<b>To:</b> ");
@ -2630,7 +2631,7 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit
string strAddress = item.first;
string strName = item.second;
uint160 hash160;
bool fMine = (AddressToHash160(strAddress, hash160) && mapPubKeys.count(hash160));
bool fMine = (AddressToHash160(strAddress, hash160) && pwalletMain->HaveKey(hash160));
wxListCtrl* plistCtrl = fMine ? m_listCtrlReceiving : m_listCtrlSending;
int nIndex = InsertLine(plistCtrl, strName, strAddress);
if (strAddress == (fMine ? strDefaultReceiving : string(strInitSelected)))
@ -2741,7 +2742,7 @@ void CAddressBookDialog::OnButtonCopy(wxCommandEvent& event)
bool CAddressBookDialog::CheckIfMine(const string& strAddress, const string& strTitle)
{
uint160 hash160;
bool fMine = (AddressToHash160(strAddress, hash160) && mapPubKeys.count(hash160));
bool fMine = (AddressToHash160(strAddress, hash160) && pwalletMain->HaveKey(hash160));
if (fMine)
wxMessageBox(_("This is one of your own addresses for receiving payments and cannot be entered in the address book. "), strTitle);
return fMine;

9
src/wallet.cpp

@ -124,7 +124,6 @@ public:
bool CWallet::EncryptWallet(const string& strWalletPassphrase)
{
CRITICAL_BLOCK(cs_mapPubKeys)
CRITICAL_BLOCK(cs_KeyStore)
CRITICAL_BLOCK(cs_vMasterKey)
CRITICAL_BLOCK(cs_pwalletdbEncryption)
@ -439,10 +438,8 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
string address;
uint160 hash160;
vector<unsigned char> vchPubKey;
if (ExtractHash160(txout.scriptPubKey, hash160))
if (ExtractHash160(txout.scriptPubKey, pwallet, hash160))
address = Hash160ToAddress(hash160);
else if (ExtractPubKey(txout.scriptPubKey, NULL, vchPubKey))
address = PubKeyToAddress(vchPubKey);
else
{
printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
@ -1136,7 +1133,7 @@ int CWallet::LoadWallet(bool& fFirstRunRet)
return nLoadWalletRet;
fFirstRunRet = vchDefaultKey.empty();
if (!HaveKey(vchDefaultKey))
if (!HaveKey(Hash160(vchDefaultKey)))
{
// Create new keyUser and set as default key
RandAddSeedPerfmon();
@ -1263,7 +1260,7 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
setKeyPool.erase(setKeyPool.begin());
if (!walletdb.ReadPool(nIndex, keypool))
throw runtime_error("ReserveKeyFromKeyPool() : read failed");
if (!HaveKey(keypool.vchPubKey))
if (!HaveKey(Hash160(keypool.vchPubKey)))
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
assert(!keypool.vchPubKey.empty());
printf("keypool reserve %"PRI64d"\n", nIndex);

6
src/wallet.h

@ -104,10 +104,10 @@ public:
}
bool IsChange(const CTxOut& txout) const
{
std::vector<unsigned char> vchPubKey;
if (ExtractPubKey(txout.scriptPubKey, this, vchPubKey))
uint160 hash160;
if (ExtractHash160(txout.scriptPubKey, this, hash160))
CRITICAL_BLOCK(cs_mapAddressBook)
if (!mapAddressBook.count(PubKeyToAddress(vchPubKey)))
if (!mapAddressBook.count(Hash160ToAddress(hash160)))
return true;
return false;
}

Loading…
Cancel
Save