changeset 2687:2cca172f83a9 draft

Encapsulate public keys in CPubKey
author Pieter Wuille <pieter.wuille@gmail.com>
date Mon, 14 May 2012 19:07:52 +0200
parents a859629a52ef
children 2c65e5d626eb
files src/base58.h src/bitcoinrpc.cpp src/init.cpp src/key.cpp src/key.h src/keystore.cpp src/keystore.h src/main.cpp src/qt/addresstablemodel.cpp src/script.cpp src/script.h src/test/multisig_tests.cpp src/wallet.cpp src/wallet.h src/walletdb.cpp src/walletdb.h
diffstat 16 files changed, 127 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/src/base58.h
+++ b/src/base58.h
@@ -275,9 +275,9 @@
         return true;
     }
 
-    void SetPubKey(const std::vector<unsigned char>& vchPubKey)
+    void SetPubKey(const CPubKey& vchPubKey)
     {
-        SetHash160(Hash160(vchPubKey));
+        SetHash160(vchPubKey.GetID());
     }
 
     bool SetScriptHash160(const uint160& hash160)
@@ -333,7 +333,7 @@
         SetHash160(hash160In);
     }
 
-    CBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
+    CBitcoinAddress(const CPubKey& vchPubKey)
     {
         SetPubKey(vchPubKey);
     }
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -590,7 +590,7 @@
         pwalletMain->TopUpKeyPool();
 
     // Generate a new key that is added to wallet
-    std::vector<unsigned char> newKey;
+    CPubKey newKey;
     if (!pwalletMain->GetKeyFromPool(newKey, false))
         throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
     CBitcoinAddress address(newKey);
@@ -611,12 +611,12 @@
     bool bKeyUsed = false;
 
     // Check if the current key has been used
-    if (!account.vchPubKey.empty())
+    if (account.vchPubKey.IsValid())
     {
         CScript scriptPubKey;
         scriptPubKey.SetBitcoinAddress(account.vchPubKey);
         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
-             it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
+             it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
              ++it)
         {
             const CWalletTx& wtx = (*it).second;
@@ -627,7 +627,7 @@
     }
 
     // Generate a new key
-    if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
+    if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
     {
         if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
             throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
@@ -1203,19 +1203,19 @@
             if (address.IsScript())
                 throw runtime_error(
                     strprintf("%s is a pay-to-script address",ks.c_str()));
-            std::vector<unsigned char> vchPubKey;
+            CPubKey vchPubKey;
             if (!pwalletMain->GetPubKey(address, vchPubKey))
                 throw runtime_error(
                     strprintf("no full public key for address %s",ks.c_str()));
-            if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
+            if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
                 throw runtime_error(" Invalid public key: "+ks);
         }
 
         // Case 2: hex public key
         else if (IsHex(ks))
         {
-            vector<unsigned char> vchPubKey = ParseHex(ks);
-            if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
+            CPubKey vchPubKey(ParseHex(ks));
+            if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey))
                 throw runtime_error(" Invalid public key: "+ks);
         }
         else
@@ -1954,9 +1954,9 @@
         if (pwalletMain->HaveKey(address))
         {
             ret.push_back(Pair("ismine", true));
-            std::vector<unsigned char> vchPubKey;
+            CPubKey vchPubKey;
             pwalletMain->GetPubKey(address, vchPubKey);
-            ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
+            ret.push_back(Pair("pubkey", HexStr(vchPubKey.Raw())));
             CKey key;
             key.SetPubKey(vchPubKey);
             ret.push_back(Pair("iscompressed", key.IsCompressed()));
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -604,7 +604,7 @@
         // Create new keyUser and set as default key
         RandAddSeedPerfmon();
 
-        std::vector<unsigned char> newDefaultKey;
+        CPubKey newDefaultKey;
         if (!pwalletMain->GetKeyFromPool(newDefaultKey, false))
             strErrors << _("Cannot initialize keypool") << "\n";
         pwalletMain->SetDefaultKey(newDefaultKey);
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -239,18 +239,18 @@
     return vchPrivKey;
 }
 
-bool CKey::SetPubKey(const std::vector<unsigned char>& vchPubKey)
+bool CKey::SetPubKey(const CPubKey& vchPubKey)
 {
-    const unsigned char* pbegin = &vchPubKey[0];
-    if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
+    const unsigned char* pbegin = &vchPubKey.vchPubKey[0];
+    if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size()))
         return false;
     fSet = true;
-    if (vchPubKey.size() == 33)
+    if (vchPubKey.vchPubKey.size() == 33)
         SetCompressedPubKey();
     return true;
 }
 
-std::vector<unsigned char> CKey::GetPubKey() const
+CPubKey CKey::GetPubKey() const
 {
     int nSize = i2o_ECPublicKey(pkey, NULL);
     if (!nSize)
@@ -259,7 +259,7 @@
     unsigned char* pbegin = &vchPubKey[0];
     if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
         throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
-    return vchPubKey;
+    return CPubKey(vchPubKey);
 }
 
 bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
--- a/src/key.h
+++ b/src/key.h
@@ -9,7 +9,9 @@
 #include <vector>
 
 #include "allocators.h"
+#include "serialize.h"
 #include "uint256.h"
+#include "util.h"
 
 #include <openssl/ec.h> // for EC_KEY definition
 
@@ -42,6 +44,39 @@
     explicit key_error(const std::string& str) : std::runtime_error(str) {}
 };
 
+class CPubKey {
+private:
+    std::vector<unsigned char> vchPubKey;
+    friend class CKey;
+
+public:
+    CPubKey() { }
+    CPubKey(const std::vector<unsigned char> &vchPubKeyIn) : vchPubKey(vchPubKeyIn) { }
+    friend bool operator==(const CPubKey &a, const CPubKey &b) { return a.vchPubKey == b.vchPubKey; }
+    friend bool operator!=(const CPubKey &a, const CPubKey &b) { return a.vchPubKey != b.vchPubKey; }
+    friend bool operator<(const CPubKey &a, const CPubKey &b) { return a.vchPubKey < b.vchPubKey; }
+
+    IMPLEMENT_SERIALIZE(
+        READWRITE(vchPubKey);
+    )
+
+    uint160 GetID() const {
+        return Hash160(vchPubKey);
+    }
+
+    uint256 GetHash() const {
+        return Hash(vchPubKey.begin(), vchPubKey.end());
+    }
+
+    bool IsValid() const {
+        return vchPubKey.size() == 33 || vchPubKey.size() == 65;
+    }
+
+    std::vector<unsigned char> Raw() const {
+        return vchPubKey;
+    }
+};
+
 
 // secure_allocator is defined in serialize.h
 // CPrivKey is a serialized private key, with all parameters included (279 bytes)
@@ -78,8 +113,8 @@
     bool SetSecret(const CSecret& vchSecret, bool fCompressed = false);
     CSecret GetSecret(bool &fCompressed) const;
     CPrivKey GetPrivKey() const;
-    bool SetPubKey(const std::vector<unsigned char>& vchPubKey);
-    std::vector<unsigned char> GetPubKey() const;
+    bool SetPubKey(const CPubKey& vchPubKey);
+    CPubKey GetPubKey() const;
 
     bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
 
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -6,7 +6,7 @@
 #include "keystore.h"
 #include "script.h"
 
-bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const
+bool CKeyStore::GetPubKey(const CBitcoinAddress &address, CPubKey &vchPubKeyOut) const
 {
     CKey key;
     if (!GetKey(address, key))
@@ -97,10 +97,10 @@
         CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
         for (; mi != mapCryptedKeys.end(); ++mi)
         {
-            const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
+            const CPubKey &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))
+            if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
                 return false;
             if (vchSecret.size() != 32)
                 return false;
@@ -128,9 +128,9 @@
             return false;
 
         std::vector<unsigned char> vchCryptedSecret;
-        std::vector<unsigned char> vchPubKey = key.GetPubKey();
+        CPubKey vchPubKey = key.GetPubKey();
         bool fCompressed;
-        if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
+        if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
             return false;
 
         if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
@@ -140,7 +140,7 @@
 }
 
 
-bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
+bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
 {
     {
         LOCK(cs_KeyStore);
@@ -162,10 +162,10 @@
         CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
         if (mi != mapCryptedKeys.end())
         {
-            const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
+            const CPubKey &vchPubKey = (*mi).second.first;
             const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
             CSecret vchSecret;
-            if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
+            if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
                 return false;
             if (vchSecret.size() != 32)
                 return false;
@@ -177,7 +177,7 @@
     return false;
 }
 
-bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
+bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, CPubKey& vchPubKeyOut) const
 {
     {
         LOCK(cs_KeyStore);
@@ -207,10 +207,10 @@
             CKey key;
             if (!key.SetSecret(mKey.second.first, mKey.second.second))
                 return false;
-            const std::vector<unsigned char> vchPubKey = key.GetPubKey();
+            const CPubKey vchPubKey = key.GetPubKey();
             std::vector<unsigned char> vchCryptedSecret;
             bool fCompressed;
-            if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
+            if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
                 return false;
             if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
                 return false;
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -28,7 +28,7 @@
     virtual bool HaveKey(const CBitcoinAddress &address) const =0;
     virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const =0;
     virtual void GetKeys(std::set<CBitcoinAddress> &setAddress) const =0;
-    virtual bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
+    virtual bool GetPubKey(const CBitcoinAddress &address, CPubKey& vchPubKeyOut) const;
 
     // Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013
     virtual bool AddCScript(const CScript& redeemScript) =0;
@@ -98,7 +98,7 @@
     virtual bool GetCScript(const uint160 &hash, CScript& redeemScriptOut) const;
 };
 
-typedef std::map<CBitcoinAddress, std::pair<std::vector<unsigned char>, std::vector<unsigned char> > > CryptedKeyMap;
+typedef std::map<CBitcoinAddress, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
 
 /** Keystore which keeps the private keys encrypted.
  * It derives from the basic key store, which is used if no encryption is active.
@@ -146,7 +146,7 @@
 
     bool Lock();
 
-    virtual bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
+    virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
     bool AddKey(const CKey& key);
     bool HaveKey(const CBitcoinAddress &address) const
     {
@@ -159,7 +159,7 @@
         return false;
     }
     bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const;
-    bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
+    bool GetPubKey(const CBitcoinAddress &address, CPubKey& vchPubKeyOut) const;
     void GetKeys(std::set<CBitcoinAddress> &setAddress) const
     {
         if (!IsCrypted())
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2304,7 +2304,7 @@
 
 bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 {
-    static map<CService, vector<unsigned char> > mapReuseKey;
+    static map<CService, CPubKey> mapReuseKey;
     RandAddSeedPerfmon();
     if (fDebug)
         printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size());
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -331,7 +331,7 @@
             editStatus = WALLET_UNLOCK_FAILURE;
             return QString();
         }
-        std::vector<unsigned char> newKey;
+        CPubKey newKey;
         if(!wallet->GetKeyFromPool(newKey, true))
         {
             editStatus = KEY_GENERATION_FAILURE;
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -1374,7 +1374,7 @@
             return false;
         else
         {
-            valtype vch;
+            CPubKey vch;
             keystore.GetPubKey(address, vch);
             scriptSigRet << vch;
         }
--- a/src/script.h
+++ b/src/script.h
@@ -320,6 +320,12 @@
         return *this;
     }
 
+    CScript& operator<<(const CPubKey& key)
+    {
+        std::vector<unsigned char> vchKey = key.Raw();
+        return (*this) << vchKey;
+    }
+
     CScript& operator<<(const CBigNum& b)
     {
         *this << b.getvch();
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -201,7 +201,7 @@
         vector<valtype> solutions;
         txnouttype whichType;
         CScript s;
-        s << OP_DUP << OP_HASH160 << Hash160(key[0].GetPubKey()) << OP_EQUALVERIFY << OP_CHECKSIG;
+        s << OP_DUP << OP_HASH160 << Hash160(key[0].GetPubKey().Raw()) << OP_EQUALVERIFY << OP_CHECKSIG;
         BOOST_CHECK(Solver(s, whichType, solutions));
         BOOST_CHECK(solutions.size() == 1);
         CBitcoinAddress addr;
@@ -214,7 +214,7 @@
         vector<valtype> solutions;
         txnouttype whichType;
         CScript s;
-        s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
+        s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey().Raw() << OP_2 << OP_CHECKMULTISIG;
         BOOST_CHECK(Solver(s, whichType, solutions));
         BOOST_CHECK_EQUAL(solutions.size(), 4);
         CBitcoinAddress addr;
@@ -227,7 +227,7 @@
         vector<valtype> solutions;
         txnouttype whichType;
         CScript s;
-        s << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
+        s << OP_1 << key[0].GetPubKey().Raw() << key[1].GetPubKey().Raw() << OP_2 << OP_CHECKMULTISIG;
         BOOST_CHECK(Solver(s, whichType, solutions));
         BOOST_CHECK_EQUAL(solutions.size(), 4);
         vector<CBitcoinAddress> addrs;
@@ -244,7 +244,7 @@
         vector<valtype> solutions;
         txnouttype whichType;
         CScript s;
-        s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
+        s << OP_2 << key[0].GetPubKey().Raw() << key[1].GetPubKey().Raw() << key[2].GetPubKey().Raw() << OP_3 << OP_CHECKMULTISIG;
         BOOST_CHECK(Solver(s, whichType, solutions));
         BOOST_CHECK(solutions.size() == 5);
     }
@@ -262,13 +262,13 @@
     }
 
     CScript a_and_b;
-    a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
+    a_and_b << OP_2 << key[0].GetPubKey().Raw() << key[1].GetPubKey().Raw() << OP_2 << OP_CHECKMULTISIG;
 
     CScript a_or_b;
-    a_or_b  << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
+    a_or_b  << OP_1 << key[0].GetPubKey().Raw() << key[1].GetPubKey().Raw() << OP_2 << OP_CHECKMULTISIG;
 
     CScript escrow;
-    escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
+    escrow << OP_2 << key[0].GetPubKey().Raw() << key[1].GetPubKey().Raw() << key[2].GetPubKey().Raw() << OP_3 << OP_CHECKMULTISIG;
 
     CTransaction txFrom;  // Funding transaction
     txFrom.vout.resize(3);
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -16,7 +16,7 @@
 // mapWallet
 //
 
-std::vector<unsigned char> CWallet::GenerateNewKey()
+CPubKey CWallet::GenerateNewKey()
 {
     bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
 
@@ -44,7 +44,7 @@
     return true;
 }
 
-bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
+bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
 {
     if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
         return false;
@@ -366,7 +366,7 @@
         {
             if (txout.scriptPubKey == scriptDefaultKey)
             {
-                std::vector<unsigned char> newDefaultKey;
+                CPubKey newDefaultKey;
                 if (GetKeyFromPool(newDefaultKey, false))
                 {
                     SetDefaultKey(newDefaultKey);
@@ -1095,7 +1095,7 @@
                     //  post-backup change.
 
                     // Reserve a new key pair from key pool
-                    vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
+                    CPubKey vchPubKey = reservekey.GetReservedKey();
                     // assert(mapKeys.count(vchPubKey));
 
                     // Fill a vout to ourself
@@ -1278,7 +1278,7 @@
 
     if (nLoadWalletRet != DB_LOAD_OK)
         return nLoadWalletRet;
-    fFirstRunRet = vchDefaultKey.empty();
+    fFirstRunRet = !vchDefaultKey.IsValid();
 
     CreateThread(ThreadFlushWalletDB, &strWalletFile);
     return DB_LOAD_OK;
@@ -1332,7 +1332,7 @@
     return false;
 }
 
-bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
+bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
 {
     if (fFileBacked)
     {
@@ -1408,7 +1408,7 @@
 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
 {
     nIndex = -1;
-    keypool.vchPubKey.clear();
+    keypool.vchPubKey = CPubKey();
     {
         LOCK(cs_wallet);
 
@@ -1425,9 +1425,9 @@
         setKeyPool.erase(setKeyPool.begin());
         if (!walletdb.ReadPool(nIndex, keypool))
             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
-        if (!HaveKey(Hash160(keypool.vchPubKey)))
+        if (!HaveKey(keypool.vchPubKey.GetID()))
             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
-        assert(!keypool.vchPubKey.empty());
+        assert(keypool.vchPubKey.IsValid());
         printf("keypool reserve %"PRI64d"\n", nIndex);
     }
 }
@@ -1468,7 +1468,7 @@
     printf("keypool return %"PRI64d"\n", nIndex);
 }
 
-bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
+bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
 {
     int64 nIndex = 0;
     CKeyPool keypool;
@@ -1477,7 +1477,7 @@
         ReserveKeyFromKeyPool(nIndex, keypool);
         if (nIndex == -1)
         {
-            if (fAllowReuse && !vchDefaultKey.empty())
+            if (fAllowReuse && vchDefaultKey.IsValid())
             {
                 result = vchDefaultKey;
                 return true;
@@ -1503,7 +1503,7 @@
     return keypool.nTime;
 }
 
-vector<unsigned char> CReserveKey::GetReservedKey()
+CPubKey CReserveKey::GetReservedKey()
 {
     if (nIndex == -1)
     {
@@ -1517,7 +1517,7 @@
             vchPubKey = pwallet->vchDefaultKey;
         }
     }
-    assert(!vchPubKey.empty());
+    assert(vchPubKey.IsValid());
     return vchPubKey;
 }
 
@@ -1526,7 +1526,7 @@
     if (nIndex != -1)
         pwallet->KeepKey(nIndex);
     nIndex = -1;
-    vchPubKey.clear();
+    vchPubKey = CPubKey();
 }
 
 void CReserveKey::ReturnKey()
@@ -1534,7 +1534,7 @@
     if (nIndex != -1)
         pwallet->ReturnKey(nIndex);
     nIndex = -1;
-    vchPubKey.clear();
+    vchPubKey = CPubKey();
 }
 
 void CWallet::GetAllReserveAddresses(set<CBitcoinAddress>& setAddress)
@@ -1550,7 +1550,7 @@
         if (!walletdb.ReadPool(id, keypool))
             throw runtime_error("GetAllReserveKeyHashes() : read failed");
         CBitcoinAddress address(keypool.vchPubKey);
-        assert(!keypool.vchPubKey.empty());
+        assert(keypool.vchPubKey.IsValid());
         if (!HaveKey(address))
             throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
         setAddress.insert(address);
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -32,14 +32,14 @@
 {
 public:
     int64 nTime;
-    std::vector<unsigned char> vchPubKey;
+    CPubKey vchPubKey;
 
     CKeyPool()
     {
         nTime = GetTime();
     }
 
-    CKeyPool(const std::vector<unsigned char>& vchPubKeyIn)
+    CKeyPool(const CPubKey& vchPubKeyIn)
     {
         nTime = GetTime();
         vchPubKey = vchPubKeyIn;
@@ -107,14 +107,14 @@
 
     std::map<CBitcoinAddress, std::string> mapAddressBook;
 
-    std::vector<unsigned char> vchDefaultKey;
+    CPubKey vchDefaultKey;
 
     // check whether we are allowed to upgrade (or already support) to the named feature
     bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
 
     // keystore implementation
     // Generate a new key
-    std::vector<unsigned char> GenerateNewKey();
+    CPubKey GenerateNewKey();
     // Adds a key to the store, and saves it to disk.
     bool AddKey(const CKey& key);
     // Adds a key to the store, without saving it to disk (used by LoadWallet)
@@ -123,9 +123,9 @@
     bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
 
     // Adds an encrypted key to the store, and saves it to disk.
-    bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
+    bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
     // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
-    bool LoadCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
+    bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
     bool AddCScript(const CScript& redeemScript);
     bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); }
 
@@ -156,7 +156,7 @@
     void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
     void KeepKey(int64 nIndex);
     void ReturnKey(int64 nIndex);
-    bool GetKeyFromPool(std::vector<unsigned char> &key, bool fAllowReuse=true);
+    bool GetKeyFromPool(CPubKey &key, bool fAllowReuse=true);
     int64 GetOldestKeyPoolTime();
     void GetAllReserveAddresses(std::set<CBitcoinAddress>& setAddress);
 
@@ -252,7 +252,7 @@
 
     bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
 
-    bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
+    bool SetDefaultKey(const CPubKey &vchPubKey);
 
     // signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
     bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
@@ -280,7 +280,7 @@
 protected:
     CWallet* pwallet;
     int64 nIndex;
-    std::vector<unsigned char> vchPubKey;
+    CPubKey vchPubKey;
 public:
     CReserveKey(CWallet* pwalletIn)
     {
@@ -295,7 +295,7 @@
     }
 
     void ReturnKey();
-    std::vector<unsigned char> GetReservedKey();
+    CPubKey GetReservedKey();
     void KeepKey();
 };
 
@@ -640,7 +640,7 @@
 class CAccount
 {
 public:
-    std::vector<unsigned char> vchPubKey;
+    CPubKey vchPubKey;
 
     CAccount()
     {
@@ -649,7 +649,7 @@
 
     void SetNull()
     {
-        vchPubKey.clear();
+        vchPubKey = CPubKey();
     }
 
     IMPLEMENT_SERIALIZE
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -104,7 +104,7 @@
 
 int CWalletDB::LoadWallet(CWallet* pwallet)
 {
-    pwallet->vchDefaultKey.clear();
+    pwallet->vchDefaultKey = CPubKey();
     int nFileVersion = 0;
     vector<uint256> vWalletUpgrade;
     bool fIsEncrypted = false;
--- a/src/walletdb.h
+++ b/src/walletdb.h
@@ -59,27 +59,27 @@
         return Erase(std::make_pair(std::string("tx"), hash));
     }
 
-    bool ReadKey(const std::vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
+    bool ReadKey(const CPubKey& vchPubKey, CPrivKey& vchPrivKey)
     {
         vchPrivKey.clear();
-        return Read(std::make_pair(std::string("key"), vchPubKey), vchPrivKey);
+        return Read(std::make_pair(std::string("key"), vchPubKey.Raw()), vchPrivKey);
     }
 
-    bool WriteKey(const std::vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
+    bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey)
     {
         nWalletDBUpdated++;
-        return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
+        return Write(std::make_pair(std::string("key"), vchPubKey.Raw()), vchPrivKey, false);
     }
 
-    bool WriteCryptedKey(const std::vector<unsigned char>& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, bool fEraseUnencryptedKey = true)
+    bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, bool fEraseUnencryptedKey = true)
     {
         nWalletDBUpdated++;
-        if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
+        if (!Write(std::make_pair(std::string("ckey"), vchPubKey.Raw()), vchCryptedSecret, false))
             return false;
         if (fEraseUnencryptedKey)
         {
-            Erase(std::make_pair(std::string("key"), vchPubKey));
-            Erase(std::make_pair(std::string("wkey"), vchPubKey));
+            Erase(std::make_pair(std::string("key"), vchPubKey.Raw()));
+            Erase(std::make_pair(std::string("wkey"), vchPubKey.Raw()));
         }
         return true;
     }
@@ -120,10 +120,10 @@
         return Read(std::string("defaultkey"), vchPubKey);
     }
 
-    bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
+    bool WriteDefaultKey(const CPubKey& vchPubKey)
     {
         nWalletDBUpdated++;
-        return Write(std::string("defaultkey"), vchPubKey);
+        return Write(std::string("defaultkey"), vchPubKey.Raw());
     }
 
     bool ReadPool(int64 nPool, CKeyPool& keypool)