aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2013-04-30 21:56:04 +0200
committerPieter Wuille <sipa@ulyssis.org>2013-05-30 05:18:42 +0200
commit5d891489ab7828ad8db15e85bb63e2f13f021a6a (patch)
tree24cd213e276977570de5b299872368bdf70ac929
parentec0004aca0a2bf11f99c9587ddb2bf8ea818d3bb (diff)
Make CPubKey statically allocated
-rw-r--r--src/hash.h11
-rw-r--r--src/key.cpp14
-rw-r--r--src/key.h85
-rw-r--r--src/rpcwallet.cpp2
-rw-r--r--src/script.cpp5
-rw-r--r--src/script.h6
-rw-r--r--src/util.h3
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)
diff --git a/src/key.h b/src/key.h
index 4da16b9cdb..1b122112f3 100644
--- a/src/key.h
+++ b/src/key.h
@@ -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);
}