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