diff options
-rw-r--r-- | src/hash.h | 11 | ||||
-rw-r--r-- | src/key.cpp | 14 | ||||
-rw-r--r-- | src/key.h | 85 | ||||
-rw-r--r-- | src/rpcwallet.cpp | 2 | ||||
-rw-r--r-- | src/script.cpp | 5 | ||||
-rw-r--r-- | src/script.h | 6 | ||||
-rw-r--r-- | src/util.h | 3 |
7 files changed, 98 insertions, 28 deletions
diff --git a/src/hash.h b/src/hash.h index eaa1780c04..536ab71165 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<unsigned char>& vch) +template<typename T1> +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<unsigned char>& vch) +{ + return Hash160(vch.begin(), vch.end()); +} + unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash); #endif diff --git a/src/key.cpp b/src/key.cpp index 75114c6afe..a99363c124 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<unsigned char> 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<unsigned char>& vchSig) @@ -63,38 +63,95 @@ public: /** An encapsulated public key. */ class CPubKey { 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; 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; } + CPubKey() { vch[0] = 0xFF; } + + CPubKey(const std::vector<unsigned char> &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; + } - IMPLEMENT_SERIALIZE( - READWRITE(vchPubKey); - ) + 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 { - 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<unsigned char> Raw() const { - return vchPubKey; + return std::vector<unsigned char>(vch, vch+size()); } }; diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 5fd400c6bb..64ee39081b 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 90066efd33..7e1d5785e8 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1895,10 +1895,11 @@ bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigne if (!key.SetPubKey(CPubKey(vch))) return false; key.SetCompressedPubKey(false); // Decompress public key - CPubKey pubkey = key.GetPubKey(); + const CPubKey pubkey = key.GetPubKey(); + assert(pubkey.size() == 65); script.resize(67); script[0] = 65; - memcpy(&script[1], &pubkey.Raw()[0], 65); + memcpy(&script[1], pubkey.begin(), 65); script[66] = OP_CHECKSIG; return true; } diff --git a/src/script.h b/src/script.h index 4b29f6273c..e639003549 100644 --- a/src/script.h +++ b/src/script.h @@ -348,8 +348,10 @@ public: CScript& operator<<(const CPubKey& key) { - std::vector<unsigned char> 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 51a694483a..b922545b9b 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<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); } |