Skip to content

Commit

Permalink
Encapsulate public keys in CPubKey
Browse files Browse the repository at this point in the history
  • Loading branch information
sipa committed May 24, 2012
1 parent f04017f commit fd61d6f
Show file tree
Hide file tree
Showing 16 changed files with 127 additions and 86 deletions.
6 changes: 3 additions & 3 deletions src/base58.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,9 @@ class CBitcoinAddress : public CBase58Data
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)
Expand Down Expand Up @@ -333,7 +333,7 @@ class CBitcoinAddress : public CBase58Data
SetHash160(hash160In);
}

CBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
CBitcoinAddress(const CPubKey& vchPubKey)
{
SetPubKey(vchPubKey);
}
Expand Down
20 changes: 10 additions & 10 deletions src/bitcoinrpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ Value getnewaddress(const Array& params, bool fHelp)
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);
Expand All @@ -611,12 +611,12 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
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;
Expand All @@ -627,7 +627,7 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
}

// 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");
Expand Down Expand Up @@ -1203,19 +1203,19 @@ Value addmultisigaddress(const Array& params, bool fHelp)
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
Expand Down Expand Up @@ -1954,9 +1954,9 @@ Value validateaddress(const Array& params, bool fHelp)
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()));
Expand Down
2 changes: 1 addition & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ bool AppInit2()
// 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);
Expand Down
12 changes: 6 additions & 6 deletions src/key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,18 +239,18 @@ CPrivKey CKey::GetPrivKey() const
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)
Expand All @@ -259,7 +259,7 @@ std::vector<unsigned char> CKey::GetPubKey() const
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)
Expand Down
39 changes: 37 additions & 2 deletions src/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -42,6 +44,39 @@ class key_error : public std::runtime_error
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)
Expand Down Expand Up @@ -78,8 +113,8 @@ class CKey
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);

Expand Down
22 changes: 11 additions & 11 deletions src/keystore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -97,10 +97,10 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
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;
Expand Down Expand Up @@ -128,9 +128,9 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
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))
Expand All @@ -140,7 +140,7 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
}


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);
Expand All @@ -162,10 +162,10 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
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;
Expand All @@ -177,7 +177,7 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
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);
Expand Down Expand Up @@ -207,10 +207,10 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
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;
Expand Down
8 changes: 4 additions & 4 deletions src/keystore.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class CKeyStore
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;
Expand Down Expand Up @@ -98,7 +98,7 @@ class CBasicKeyStore : public CKeyStore
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.
Expand Down Expand Up @@ -146,7 +146,7 @@ class CCryptoKeyStore : public CBasicKeyStore

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
{
Expand All @@ -159,7 +159,7 @@ class CCryptoKeyStore : public CBasicKeyStore
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())
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2304,7 +2304,7 @@ unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };

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());
Expand Down
2 changes: 1 addition & 1 deletion src/qt/addresstablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
editStatus = WALLET_UNLOCK_FAILURE;
return QString();
}
std::vector<unsigned char> newKey;
CPubKey newKey;
if(!wallet->GetKeyFromPool(newKey, true))
{
editStatus = KEY_GENERATION_FAILURE;
Expand Down
2 changes: 1 addition & 1 deletion src/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,7 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
return false;
else
{
valtype vch;
CPubKey vch;
keystore.GetPubKey(address, vch);
scriptSigRet << vch;
}
Expand Down
6 changes: 6 additions & 0 deletions src/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ class CScript : public std::vector<unsigned char>
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();
Expand Down
14 changes: 7 additions & 7 deletions src/test/multisig_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
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;
Expand All @@ -214,7 +214,7 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
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;
Expand All @@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
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;
Expand All @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
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);
}
Expand All @@ -262,13 +262,13 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
}

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);
Expand Down
Loading

0 comments on commit fd61d6f

Please sign in to comment.