From 5d891489ab7828ad8db15e85bb63e2f13f021a6a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 30 Apr 2013 21:56:04 +0200 Subject: [PATCH] Make CPubKey statically allocated --- src/hash.h | 11 ++++-- src/key.cpp | 14 ++++---- src/key.h | 85 +++++++++++++++++++++++++++++++++++++++-------- src/rpcwallet.cpp | 2 +- src/script.cpp | 5 +-- src/script.h | 6 ++-- src/util.h | 3 +- 7 files changed, 98 insertions(+), 28 deletions(-) diff --git a/src/hash.h b/src/hash.h index eaa1780c0..536ab7116 100644 --- a/src/hash.h +++ b/src/hash.h @@ -105,15 +105,22 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL return ss.GetHash(); } -inline uint160 Hash160(const std::vector& vch) +template +inline uint160 Hash160(const T1 pbegin, const T1 pend) { + static unsigned char pblank[1]; 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; RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); return hash2; } +inline uint160 Hash160(const std::vector& vch) +{ + return Hash160(vch.begin(), vch.end()); +} + unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& vDataToHash); #endif diff --git a/src/key.cpp b/src/key.cpp index 75114c6af..a99363c12 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -258,11 +258,11 @@ CPrivKey CKey::GetPrivKey() const bool CKey::SetPubKey(const CPubKey& vchPubKey) { - const unsigned char* pbegin = &vchPubKey.vchPubKey[0]; - if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size())) + const unsigned char* pbegin = vchPubKey.begin(); + if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size())) { fSet = true; - if (vchPubKey.vchPubKey.size() == 33) + if (vchPubKey.size() == 33) SetCompressedPubKey(); return true; } @@ -276,11 +276,13 @@ CPubKey CKey::GetPubKey() const int nSize = i2o_ECPublicKey(pkey, NULL); if (!nSize) throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed"); - std::vector vchPubKey(nSize, 0); - unsigned char* pbegin = &vchPubKey[0]; + assert(nSize <= 65); + CPubKey ret; + unsigned char *pbegin = ret.begin(); if (i2o_ECPublicKey(pkey, &pbegin) != nSize) 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& vchSig) diff --git a/src/key.h b/src/key.h index 4da16b9cd..1b122112f 100644 --- a/src/key.h +++ b/src/key.h @@ -63,38 +63,95 @@ public: /** An encapsulated public key. */ class CPubKey { private: - std::vector 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; public: - CPubKey() { } - CPubKey(const std::vector &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; } + CPubKey() { vch[0] = 0xFF; } - IMPLEMENT_SERIALIZE( - READWRITE(vchPubKey); - ) + CPubKey(const std::vector &vchPubKeyIn) { + 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 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 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 { - return CKeyID(Hash160(vchPubKey)); + return CKeyID(Hash160(vch, vch+size())); } uint256 GetHash() const { - return Hash(vchPubKey.begin(), vchPubKey.end()); + return Hash(vch, vch+size()); } bool IsValid() const { - return vchPubKey.size() == 33 || vchPubKey.size() == 65; + return size() > 0; } bool IsCompressed() const { - return vchPubKey.size() == 33; + return size() == 33; } std::vector Raw() const { - return vchPubKey; + return std::vector(vch, vch+size()); } }; diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 5fd400c6b..64ee39081 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1445,7 +1445,7 @@ public: CPubKey vchPubKey; pwalletMain->GetPubKey(keyID, vchPubKey); 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())); return obj; } diff --git a/src/script.cpp b/src/script.cpp index 90066efd3..7e1d5785e 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1895,10 +1895,11 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector vchKey = key.Raw(); - return (*this) << vchKey; + assert(key.size() < OP_PUSHDATA1); + insert(end(), (unsigned char)key.size()); + insert(end(), key.begin(), key.end()); + return *this; } CScript& operator<<(const CBigNum& b) diff --git a/src/util.h b/src/util.h index 51a694483..b922545b9 100644 --- a/src/util.h +++ b/src/util.h @@ -300,7 +300,8 @@ std::string HexStr(const T itbegin, const T itend, bool fSpaces=false) return rv; } -inline std::string HexStr(const std::vector& vch, bool fSpaces=false) +template +inline std::string HexStr(const T& vch, bool fSpaces=false) { return HexStr(vch.begin(), vch.end(), fSpaces); }