]>
Commit | Line | Data |
---|---|---|
d2e74c55 | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
f914f1a7 | 2 | // Copyright (c) 2009-2014 The Bitcoin Core developers |
b4347f60 | 3 | // Distributed under the MIT software license, see the accompanying |
d2e74c55 CF |
4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
5 | ||
6 | #ifndef BITCOIN_PUBKEY_H | |
7 | #define BITCOIN_PUBKEY_H | |
8 | ||
9 | #include "hash.h" | |
10 | #include "serialize.h" | |
11 | #include "uint256.h" | |
12 | ||
13 | #include <stdexcept> | |
14 | #include <vector> | |
15 | ||
16 | /** | |
17 | * secp256k1: | |
18 | * const unsigned int PRIVATE_KEY_SIZE = 279; | |
19 | * const unsigned int PUBLIC_KEY_SIZE = 65; | |
20 | * const unsigned int SIGNATURE_SIZE = 72; | |
21 | * | |
22 | * see www.keylength.com | |
23 | * script supports up to 75 for single byte push | |
24 | */ | |
25 | ||
26 | /** A reference to a CKey: the Hash160 of its serialized public key */ | |
27 | class CKeyID : public uint160 | |
28 | { | |
29 | public: | |
4f152496 | 30 | CKeyID() : uint160() {} |
d2e74c55 CF |
31 | CKeyID(const uint160& in) : uint160(in) {} |
32 | }; | |
33 | ||
a5748996 | 34 | typedef uint256 ChainCode; |
8cf1485f | 35 | |
d2e74c55 CF |
36 | /** An encapsulated public key. */ |
37 | class CPubKey | |
38 | { | |
39 | private: | |
40 | ||
41 | /** | |
42 | * Just store the serialized data. | |
43 | * Its length can very cheaply be computed from the first byte. | |
44 | */ | |
45 | unsigned char vch[65]; | |
46 | ||
47 | //! Compute the length of a pubkey with a given first byte. | |
48 | unsigned int static GetLen(unsigned char chHeader) | |
49 | { | |
50 | if (chHeader == 2 || chHeader == 3) | |
51 | return 33; | |
52 | if (chHeader == 4 || chHeader == 6 || chHeader == 7) | |
53 | return 65; | |
54 | return 0; | |
55 | } | |
56 | ||
57 | //! Set this key data to be invalid | |
58 | void Invalidate() | |
59 | { | |
60 | vch[0] = 0xFF; | |
61 | } | |
62 | ||
63 | public: | |
64 | //! Construct an invalid public key. | |
65 | CPubKey() | |
66 | { | |
67 | Invalidate(); | |
68 | } | |
69 | ||
70 | //! Initialize a public key using begin/end iterators to byte data. | |
71 | template <typename T> | |
72 | void Set(const T pbegin, const T pend) | |
73 | { | |
74 | int len = pend == pbegin ? 0 : GetLen(pbegin[0]); | |
75 | if (len && len == (pend - pbegin)) | |
76 | memcpy(vch, (unsigned char*)&pbegin[0], len); | |
77 | else | |
78 | Invalidate(); | |
79 | } | |
80 | ||
81 | //! Construct a public key using begin/end iterators to byte data. | |
82 | template <typename T> | |
83 | CPubKey(const T pbegin, const T pend) | |
84 | { | |
85 | Set(pbegin, pend); | |
86 | } | |
87 | ||
88 | //! Construct a public key from a byte vector. | |
89 | CPubKey(const std::vector<unsigned char>& vch) | |
90 | { | |
91 | Set(vch.begin(), vch.end()); | |
92 | } | |
93 | ||
94 | //! Simple read-only vector-like interface to the pubkey data. | |
95 | unsigned int size() const { return GetLen(vch[0]); } | |
96 | const unsigned char* begin() const { return vch; } | |
97 | const unsigned char* end() const { return vch + size(); } | |
98 | const unsigned char& operator[](unsigned int pos) const { return vch[pos]; } | |
99 | ||
100 | //! Comparator implementation. | |
101 | friend bool operator==(const CPubKey& a, const CPubKey& b) | |
102 | { | |
103 | return a.vch[0] == b.vch[0] && | |
104 | memcmp(a.vch, b.vch, a.size()) == 0; | |
105 | } | |
106 | friend bool operator!=(const CPubKey& a, const CPubKey& b) | |
107 | { | |
108 | return !(a == b); | |
109 | } | |
110 | friend bool operator<(const CPubKey& a, const CPubKey& b) | |
111 | { | |
112 | return a.vch[0] < b.vch[0] || | |
113 | (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0); | |
114 | } | |
115 | ||
116 | //! Implement serialization, as if this was a byte vector. | |
117 | unsigned int GetSerializeSize(int nType, int nVersion) const | |
118 | { | |
119 | return size() + 1; | |
120 | } | |
121 | template <typename Stream> | |
122 | void Serialize(Stream& s, int nType, int nVersion) const | |
123 | { | |
124 | unsigned int len = size(); | |
125 | ::WriteCompactSize(s, len); | |
126 | s.write((char*)vch, len); | |
127 | } | |
128 | template <typename Stream> | |
129 | void Unserialize(Stream& s, int nType, int nVersion) | |
130 | { | |
131 | unsigned int len = ::ReadCompactSize(s); | |
132 | if (len <= 65) { | |
133 | s.read((char*)vch, len); | |
134 | } else { | |
135 | // invalid pubkey, skip available data | |
136 | char dummy; | |
137 | while (len--) | |
138 | s.read(&dummy, 1); | |
139 | Invalidate(); | |
140 | } | |
141 | } | |
142 | ||
143 | //! Get the KeyID of this public key (hash of its serialization) | |
144 | CKeyID GetID() const | |
145 | { | |
146 | return CKeyID(Hash160(vch, vch + size())); | |
147 | } | |
148 | ||
149 | //! Get the 256-bit hash of this public key. | |
150 | uint256 GetHash() const | |
151 | { | |
152 | return Hash(vch, vch + size()); | |
153 | } | |
154 | ||
155 | /* | |
156 | * Check syntactic correctness. | |
157 | * | |
158 | * Note that this is consensus critical as CheckSig() calls it! | |
159 | */ | |
160 | bool IsValid() const | |
161 | { | |
162 | return size() > 0; | |
163 | } | |
164 | ||
165 | //! fully validate whether this is a valid public key (more expensive than IsValid()) | |
166 | bool IsFullyValid() const; | |
167 | ||
168 | //! Check whether this is a compressed public key. | |
169 | bool IsCompressed() const | |
170 | { | |
171 | return size() == 33; | |
172 | } | |
173 | ||
174 | /** | |
175 | * Verify a DER signature (~72 bytes). | |
176 | * If this public key is not fully valid, the return value will be false. | |
177 | */ | |
178 | bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const; | |
179 | ||
180 | //! Recover a public key from a compact signature. | |
181 | bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig); | |
182 | ||
183 | //! Turn this public key into an uncompressed public key. | |
184 | bool Decompress(); | |
185 | ||
186 | //! Derive BIP32 child pubkey. | |
a5748996 | 187 | bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const; |
d2e74c55 CF |
188 | }; |
189 | ||
190 | struct CExtPubKey { | |
191 | unsigned char nDepth; | |
192 | unsigned char vchFingerprint[4]; | |
193 | unsigned int nChild; | |
a5748996 | 194 | ChainCode chaincode; |
d2e74c55 CF |
195 | CPubKey pubkey; |
196 | ||
8cf1485f | 197 | friend bool operator==(const CExtPubKey &a, const CExtPubKey &b) |
d2e74c55 CF |
198 | { |
199 | return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && | |
a5748996 | 200 | a.chaincode == b.chaincode && a.pubkey == b.pubkey; |
d2e74c55 CF |
201 | } |
202 | ||
203 | void Encode(unsigned char code[74]) const; | |
204 | void Decode(const unsigned char code[74]); | |
205 | bool Derive(CExtPubKey& out, unsigned int nChild) const; | |
206 | }; | |
207 | ||
208 | #endif // BITCOIN_PUBKEY_H |