Make CPubKey statically allocated

This commit is contained in:
Pieter Wuille 2013-04-30 21:56:04 +02:00 committed by Pieter Wuille
parent ec0004aca0
commit 5d891489ab
7 changed files with 98 additions and 28 deletions

View file

@ -105,15 +105,22 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
return ss.GetHash(); return ss.GetHash();
} }
inline uint160 Hash160(const std::vector<unsigned char>& vch) template<typename T1>
inline uint160 Hash160(const T1 pbegin, const T1 pend)
{ {
static unsigned char pblank[1];
uint256 hash1; uint256 hash1;
SHA256(&vch[0], vch.size(), (unsigned char*)&hash1); SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);
uint160 hash2; uint160 hash2;
RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
return hash2; return hash2;
} }
inline uint160 Hash160(const std::vector<unsigned char>& vch)
{
return Hash160(vch.begin(), vch.end());
}
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash); unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
#endif #endif

View file

@ -258,11 +258,11 @@ CPrivKey CKey::GetPrivKey() const
bool CKey::SetPubKey(const CPubKey& vchPubKey) bool CKey::SetPubKey(const CPubKey& vchPubKey)
{ {
const unsigned char* pbegin = &vchPubKey.vchPubKey[0]; const unsigned char* pbegin = vchPubKey.begin();
if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size())) if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
{ {
fSet = true; fSet = true;
if (vchPubKey.vchPubKey.size() == 33) if (vchPubKey.size() == 33)
SetCompressedPubKey(); SetCompressedPubKey();
return true; return true;
} }
@ -276,11 +276,13 @@ CPubKey CKey::GetPubKey() const
int nSize = i2o_ECPublicKey(pkey, NULL); int nSize = i2o_ECPublicKey(pkey, NULL);
if (!nSize) if (!nSize)
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed"); throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
std::vector<unsigned char> vchPubKey(nSize, 0); assert(nSize <= 65);
unsigned char* pbegin = &vchPubKey[0]; CPubKey ret;
unsigned char *pbegin = ret.begin();
if (i2o_ECPublicKey(pkey, &pbegin) != nSize) if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size"); throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
return CPubKey(vchPubKey); assert((int)ret.size() == nSize);
return ret;
} }
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig) bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)

View file

@ -63,38 +63,95 @@ public:
/** An encapsulated public key. */ /** An encapsulated public key. */
class CPubKey { class CPubKey {
private: private:
std::vector<unsigned char> vchPubKey; unsigned char vch[65];
unsigned int static GetLen(unsigned char chHeader) {
if (chHeader == 2 || chHeader == 3)
return 33;
if (chHeader == 4 || chHeader == 6 || chHeader == 7)
return 65;
return 0;
}
unsigned char *begin() {
return vch;
}
friend class CKey; friend class CKey;
public: public:
CPubKey() { } CPubKey() { vch[0] = 0xFF; }
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( CPubKey(const std::vector<unsigned char> &vchPubKeyIn) {
READWRITE(vchPubKey); int len = vchPubKeyIn.empty() ? 0 : GetLen(vchPubKeyIn[0]);
) if (len) {
memcpy(vch, &vchPubKeyIn[0], len);
} else {
vch[0] = 0xFF;
}
}
unsigned int size() const {
return GetLen(vch[0]);
}
const unsigned char *begin() const {
return vch;
}
const unsigned char *end() const {
return vch+size();
}
friend bool operator==(const CPubKey &a, const CPubKey &b) { return memcmp(a.vch, b.vch, a.size()) == 0; }
friend bool operator!=(const CPubKey &a, const CPubKey &b) { return memcmp(a.vch, b.vch, a.size()) != 0; }
friend bool operator<(const CPubKey &a, const CPubKey &b) {
return a.vch[0] < b.vch[0] ||
(a.vch[0] == b.vch[0] && memcmp(a.vch+1, b.vch+1, a.size() - 1) < 0);
}
unsigned int GetSerializeSize(int nType, int nVersion) const {
return size() + 1;
}
template<typename Stream> void Serialize(Stream &s, int nType, int nVersion) const {
unsigned int len = size();
::Serialize(s, VARINT(len), nType, nVersion);
s.write((char*)vch, len);
}
template<typename Stream> void Unserialize(Stream &s, int nType, int nVersion) {
unsigned int len;
::Unserialize(s, VARINT(len), nType, nVersion);
if (len <= 65) {
s.read((char*)vch, len);
} else {
// invalid pubkey
vch[0] = 0xFF;
char dummy;
while (len--)
s.read(&dummy, 1);
}
}
CKeyID GetID() const { CKeyID GetID() const {
return CKeyID(Hash160(vchPubKey)); return CKeyID(Hash160(vch, vch+size()));
} }
uint256 GetHash() const { uint256 GetHash() const {
return Hash(vchPubKey.begin(), vchPubKey.end()); return Hash(vch, vch+size());
} }
bool IsValid() const { bool IsValid() const {
return vchPubKey.size() == 33 || vchPubKey.size() == 65; return size() > 0;
} }
bool IsCompressed() const { bool IsCompressed() const {
return vchPubKey.size() == 33; return size() == 33;
} }
std::vector<unsigned char> Raw() const { std::vector<unsigned char> Raw() const {
return vchPubKey; return std::vector<unsigned char>(vch, vch+size());
} }
}; };

View file

@ -1445,7 +1445,7 @@ public:
CPubKey vchPubKey; CPubKey vchPubKey;
pwalletMain->GetPubKey(keyID, vchPubKey); pwalletMain->GetPubKey(keyID, vchPubKey);
obj.push_back(Pair("isscript", false)); obj.push_back(Pair("isscript", false));
obj.push_back(Pair("pubkey", HexStr(vchPubKey.Raw()))); obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
return obj; return obj;
} }

View file

@ -1895,10 +1895,11 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigne
if (!key.SetPubKey(CPubKey(vch))) if (!key.SetPubKey(CPubKey(vch)))
return false; return false;
key.SetCompressedPubKey(false); // Decompress public key key.SetCompressedPubKey(false); // Decompress public key
CPubKey pubkey = key.GetPubKey(); const CPubKey pubkey = key.GetPubKey();
assert(pubkey.size() == 65);
script.resize(67); script.resize(67);
script[0] = 65; script[0] = 65;
memcpy(&script[1], &pubkey.Raw()[0], 65); memcpy(&script[1], pubkey.begin(), 65);
script[66] = OP_CHECKSIG; script[66] = OP_CHECKSIG;
return true; return true;
} }

View file

@ -348,8 +348,10 @@ public:
CScript& operator<<(const CPubKey& key) CScript& operator<<(const CPubKey& key)
{ {
std::vector<unsigned char> vchKey = key.Raw(); assert(key.size() < OP_PUSHDATA1);
return (*this) << vchKey; insert(end(), (unsigned char)key.size());
insert(end(), key.begin(), key.end());
return *this;
} }
CScript& operator<<(const CBigNum& b) CScript& operator<<(const CBigNum& b)

View file

@ -300,7 +300,8 @@ std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
return rv; return rv;
} }
inline std::string HexStr(const std::vector<unsigned char>& vch, bool fSpaces=false) template<typename T>
inline std::string HexStr(const T& vch, bool fSpaces=false)
{ {
return HexStr(vch.begin(), vch.end(), fSpaces); return HexStr(vch.begin(), vch.end(), fSpaces);
} }