Coverage Report

Created: 2024-08-21 05:08

/workdir/bitcoin/src/pubkey.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
2
// Copyright (c) 2009-2022 The Bitcoin Core developers
3
// Copyright (c) 2017 The Zcash developers
4
// Distributed under the MIT software license, see the accompanying
5
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
6
7
#ifndef BITCOIN_PUBKEY_H
8
#define BITCOIN_PUBKEY_H
9
10
#include <hash.h>
11
#include <serialize.h>
12
#include <span.h>
13
#include <uint256.h>
14
15
#include <cstring>
16
#include <optional>
17
#include <vector>
18
19
const unsigned int BIP32_EXTKEY_SIZE = 74;
20
const unsigned int BIP32_EXTKEY_WITH_VERSION_SIZE = 78;
21
22
/** A reference to a CKey: the Hash160 of its serialized public key */
23
class CKeyID : public uint160
24
{
25
public:
26
0
    CKeyID() : uint160() {}
27
0
    explicit CKeyID(const uint160& in) : uint160(in) {}
28
};
29
30
typedef uint256 ChainCode;
31
32
/** An encapsulated public key. */
33
class CPubKey
34
{
35
public:
36
    /**
37
     * secp256k1:
38
     */
39
    static constexpr unsigned int SIZE                   = 65;
40
    static constexpr unsigned int COMPRESSED_SIZE        = 33;
41
    static constexpr unsigned int SIGNATURE_SIZE         = 72;
42
    static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65;
43
    /**
44
     * see www.keylength.com
45
     * script supports up to 75 for single byte push
46
     */
47
    static_assert(
48
        SIZE >= COMPRESSED_SIZE,
49
        "COMPRESSED_SIZE is larger than SIZE");
50
51
private:
52
53
    /**
54
     * Just store the serialized data.
55
     * Its length can very cheaply be computed from the first byte.
56
     */
57
    unsigned char vch[SIZE];
58
59
    //! Compute the length of a pubkey with a given first byte.
60
    unsigned int static GetLen(unsigned char chHeader)
61
0
    {
62
0
        if (chHeader == 2 || chHeader == 3)
  Branch (62:13): [True: 0, False: 0]
  Branch (62:30): [True: 0, False: 0]
63
0
            return COMPRESSED_SIZE;
64
0
        if (chHeader == 4 || chHeader == 6 || chHeader == 7)
  Branch (64:13): [True: 0, False: 0]
  Branch (64:30): [True: 0, False: 0]
  Branch (64:47): [True: 0, False: 0]
65
0
            return SIZE;
66
0
        return 0;
67
0
    }
68
69
    //! Set this key data to be invalid
70
    void Invalidate()
71
0
    {
72
0
        vch[0] = 0xFF;
73
0
    }
74
75
public:
76
77
0
    bool static ValidSize(const std::vector<unsigned char> &vch) {
78
0
      return vch.size() > 0 && GetLen(vch[0]) == vch.size();
  Branch (78:14): [True: 0, False: 0]
  Branch (78:32): [True: 0, False: 0]
79
0
    }
80
81
    //! Construct an invalid public key.
82
    CPubKey()
83
0
    {
84
0
        Invalidate();
85
0
    }
86
87
    //! Initialize a public key using begin/end iterators to byte data.
88
    template <typename T>
89
    void Set(const T pbegin, const T pend)
90
0
    {
91
0
        int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
  Branch (91:19): [True: 0, False: 0]
  Branch (91:19): [True: 0, False: 0]
  Branch (91:19): [True: 0, False: 0]
  Branch (91:19): [True: 0, False: 0]
92
0
        if (len && len == (pend - pbegin))
  Branch (92:13): [True: 0, False: 0]
  Branch (92:20): [True: 0, False: 0]
  Branch (92:13): [True: 0, False: 0]
  Branch (92:20): [True: 0, False: 0]
  Branch (92:13): [True: 0, False: 0]
  Branch (92:20): [True: 0, False: 0]
  Branch (92:13): [True: 0, False: 0]
  Branch (92:20): [True: 0, False: 0]
93
0
            memcpy(vch, (unsigned char*)&pbegin[0], len);
94
0
        else
95
0
            Invalidate();
96
0
    }
Unexecuted instantiation: void CPubKey::Set<unsigned char const*>(unsigned char const*, unsigned char const*)
Unexecuted instantiation: void CPubKey::Set<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >)
Unexecuted instantiation: void CPubKey::Set<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > >)
Unexecuted instantiation: void CPubKey::Set<unsigned char*>(unsigned char*, unsigned char*)
97
98
    //! Construct a public key using begin/end iterators to byte data.
99
    template <typename T>
100
    CPubKey(const T pbegin, const T pend)
101
0
    {
102
0
        Set(pbegin, pend);
103
0
    }
Unexecuted instantiation: CPubKey::CPubKey<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >)
Unexecuted instantiation: CPubKey::CPubKey<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > > >(__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > >)
Unexecuted instantiation: CPubKey::CPubKey<unsigned char*>(unsigned char*, unsigned char*)
104
105
    //! Construct a public key from a byte vector.
106
    explicit CPubKey(Span<const uint8_t> _vch)
107
0
    {
108
0
        Set(_vch.begin(), _vch.end());
109
0
    }
110
111
    //! Simple read-only vector-like interface to the pubkey data.
112
0
    unsigned int size() const { return GetLen(vch[0]); }
113
0
    const unsigned char* data() const { return vch; }
114
0
    const unsigned char* begin() const { return vch; }
115
0
    const unsigned char* end() const { return vch + size(); }
116
0
    const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
117
118
    //! Comparator implementation.
119
    friend bool operator==(const CPubKey& a, const CPubKey& b)
120
0
    {
121
0
        return a.vch[0] == b.vch[0] &&
  Branch (121:16): [True: 0, False: 0]
122
0
               memcmp(a.vch, b.vch, a.size()) == 0;
  Branch (122:16): [True: 0, False: 0]
123
0
    }
124
    friend bool operator!=(const CPubKey& a, const CPubKey& b)
125
0
    {
126
0
        return !(a == b);
127
0
    }
128
    friend bool operator<(const CPubKey& a, const CPubKey& b)
129
0
    {
130
0
        return a.vch[0] < b.vch[0] ||
  Branch (130:16): [True: 0, False: 0]
131
0
               (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
  Branch (131:17): [True: 0, False: 0]
  Branch (131:41): [True: 0, False: 0]
132
0
    }
133
    friend bool operator>(const CPubKey& a, const CPubKey& b)
134
0
    {
135
0
        return a.vch[0] > b.vch[0] ||
  Branch (135:16): [True: 0, False: 0]
136
0
               (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) > 0);
  Branch (136:17): [True: 0, False: 0]
  Branch (136:41): [True: 0, False: 0]
137
0
    }
138
139
    //! Implement serialization, as if this was a byte vector.
140
    template <typename Stream>
141
    void Serialize(Stream& s) const
142
0
    {
143
0
        unsigned int len = size();
144
0
        ::WriteCompactSize(s, len);
145
0
        s << Span{vch, len};
146
0
    }
147
    template <typename Stream>
148
    void Unserialize(Stream& s)
149
0
    {
150
0
        const unsigned int len(::ReadCompactSize(s));
151
0
        if (len <= SIZE) {
  Branch (151:13): [True: 0, False: 0]
152
0
            s >> Span{vch, len};
153
0
            if (len != size()) {
  Branch (153:17): [True: 0, False: 0]
154
0
                Invalidate();
155
0
            }
156
0
        } else {
157
            // invalid pubkey, skip available data
158
0
            s.ignore(len);
159
0
            Invalidate();
160
0
        }
161
0
    }
162
163
    //! Get the KeyID of this public key (hash of its serialization)
164
    CKeyID GetID() const
165
0
    {
166
0
        return CKeyID(Hash160(Span{vch}.first(size())));
167
0
    }
168
169
    //! Get the 256-bit hash of this public key.
170
    uint256 GetHash() const
171
0
    {
172
0
        return Hash(Span{vch}.first(size()));
173
0
    }
174
175
    /*
176
     * Check syntactic correctness.
177
     *
178
     * When setting a pubkey (Set()) or deserializing fails (its header bytes
179
     * don't match the length of the data), the size is set to 0. Thus,
180
     * by checking size, one can observe whether Set() or deserialization has
181
     * failed.
182
     *
183
     * This does not check for more than that. In particular, it does not verify
184
     * that the coordinates correspond to a point on the curve (see IsFullyValid()
185
     * for that instead).
186
     *
187
     * Note that this is consensus critical as CheckECDSASignature() calls it!
188
     */
189
    bool IsValid() const
190
0
    {
191
0
        return size() > 0;
192
0
    }
193
194
    /** Check if a public key is a syntactically valid compressed or uncompressed key. */
195
    bool IsValidNonHybrid() const noexcept
196
0
    {
197
0
        return size() > 0 && (vch[0] == 0x02 || vch[0] == 0x03 || vch[0] == 0x04);
  Branch (197:16): [True: 0, False: 0]
  Branch (197:31): [True: 0, False: 0]
  Branch (197:49): [True: 0, False: 0]
  Branch (197:67): [True: 0, False: 0]
198
0
    }
199
200
    //! fully validate whether this is a valid public key (more expensive than IsValid())
201
    bool IsFullyValid() const;
202
203
    //! Check whether this is a compressed public key.
204
    bool IsCompressed() const
205
0
    {
206
0
        return size() == COMPRESSED_SIZE;
207
0
    }
208
209
    /**
210
     * Verify a DER signature (~72 bytes).
211
     * If this public key is not fully valid, the return value will be false.
212
     */
213
    bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
214
215
    /**
216
     * Check whether a signature is normalized (lower-S).
217
     */
218
    static bool CheckLowS(const std::vector<unsigned char>& vchSig);
219
220
    //! Recover a public key from a compact signature.
221
    bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
222
223
    //! Turn this public key into an uncompressed public key.
224
    bool Decompress();
225
226
    //! Derive BIP32 child pubkey.
227
    [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
228
};
229
230
class XOnlyPubKey
231
{
232
private:
233
    uint256 m_keydata;
234
235
public:
236
    /** Nothing Up My Sleeve point H
237
     *  Used as an internal key for provably disabling the key path spend
238
     *  see BIP341 for more details */
239
    static const XOnlyPubKey NUMS_H;
240
241
    /** Construct an empty x-only pubkey. */
242
0
    XOnlyPubKey() = default;
243
244
    XOnlyPubKey(const XOnlyPubKey&) = default;
245
    XOnlyPubKey& operator=(const XOnlyPubKey&) = default;
246
247
    /** Determine if this pubkey is fully valid. This is true for approximately 50% of all
248
     *  possible 32-byte arrays. If false, VerifySchnorr, CheckTapTweak and CreateTapTweak
249
     *  will always fail. */
250
    bool IsFullyValid() const;
251
252
    /** Test whether this is the 0 key (the result of default construction). This implies
253
     *  !IsFullyValid(). */
254
0
    bool IsNull() const { return m_keydata.IsNull(); }
255
256
    /** Construct an x-only pubkey from exactly 32 bytes. */
257
    explicit XOnlyPubKey(Span<const unsigned char> bytes);
258
259
    /** Construct an x-only pubkey from a normal pubkey. */
260
0
    explicit XOnlyPubKey(const CPubKey& pubkey) : XOnlyPubKey(Span{pubkey}.subspan(1, 32)) {}
261
262
    /** Verify a Schnorr signature against this public key.
263
     *
264
     * sigbytes must be exactly 64 bytes.
265
     */
266
    bool VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const;
267
268
    /** Compute the Taproot tweak as specified in BIP341, with *this as internal
269
     * key:
270
     *  - if merkle_root == nullptr: H_TapTweak(xonly_pubkey)
271
     *  - otherwise:                 H_TapTweak(xonly_pubkey || *merkle_root)
272
     *
273
     * Note that the behavior of this function with merkle_root != nullptr is
274
     * consensus critical.
275
     */
276
    uint256 ComputeTapTweakHash(const uint256* merkle_root) const;
277
278
    /** Verify that this is a Taproot tweaked output point, against a specified internal key,
279
     *  Merkle root, and parity. */
280
    bool CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const;
281
282
    /** Construct a Taproot tweaked output point with this point as internal key. */
283
    std::optional<std::pair<XOnlyPubKey, bool>> CreateTapTweak(const uint256* merkle_root) const;
284
285
    /** Returns a list of CKeyIDs for the CPubKeys that could have been used to create this XOnlyPubKey.
286
     * This is needed for key lookups since keys are indexed by CKeyID.
287
     */
288
    std::vector<CKeyID> GetKeyIDs() const;
289
290
    CPubKey GetEvenCorrespondingCPubKey() const;
291
292
0
    const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
293
0
    static constexpr size_t size() { return decltype(m_keydata)::size(); }
294
0
    const unsigned char* data() const { return m_keydata.begin(); }
295
0
    const unsigned char* begin() const { return m_keydata.begin(); }
296
0
    const unsigned char* end() const { return m_keydata.end(); }
297
0
    unsigned char* data() { return m_keydata.begin(); }
298
0
    unsigned char* begin() { return m_keydata.begin(); }
299
0
    unsigned char* end() { return m_keydata.end(); }
300
0
    bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; }
301
0
    bool operator!=(const XOnlyPubKey& other) const { return m_keydata != other.m_keydata; }
302
0
    bool operator<(const XOnlyPubKey& other) const { return m_keydata < other.m_keydata; }
303
304
    //! Implement serialization without length prefixes since it is a fixed length
305
0
    SERIALIZE_METHODS(XOnlyPubKey, obj) { READWRITE(obj.m_keydata); }
Unexecuted instantiation: void XOnlyPubKey::SerializationOps<SpanReader, XOnlyPubKey, ActionUnserialize>(XOnlyPubKey&, SpanReader&, ActionUnserialize)
Unexecuted instantiation: void XOnlyPubKey::SerializationOps<DataStream, XOnlyPubKey, ActionUnserialize>(XOnlyPubKey&, DataStream&, ActionUnserialize)
Unexecuted instantiation: void XOnlyPubKey::SerializationOps<SizeComputer, XOnlyPubKey const, ActionSerialize>(XOnlyPubKey const&, SizeComputer&, ActionSerialize)
Unexecuted instantiation: void XOnlyPubKey::SerializationOps<DataStream, XOnlyPubKey const, ActionSerialize>(XOnlyPubKey const&, DataStream&, ActionSerialize)
306
};
307
308
/** An ElligatorSwift-encoded public key. */
309
struct EllSwiftPubKey
310
{
311
private:
312
    static constexpr size_t SIZE = 64;
313
    std::array<std::byte, SIZE> m_pubkey;
314
315
public:
316
    /** Default constructor creates all-zero pubkey (which is valid). */
317
    EllSwiftPubKey() noexcept = default;
318
319
    /** Construct a new ellswift public key from a given serialization. */
320
    EllSwiftPubKey(Span<const std::byte> ellswift) noexcept;
321
322
    /** Decode to normal compressed CPubKey (for debugging purposes). */
323
    CPubKey Decode() const;
324
325
    // Read-only access for serialization.
326
0
    const std::byte* data() const { return m_pubkey.data(); }
327
0
    static constexpr size_t size() { return SIZE; }
328
0
    auto begin() const { return m_pubkey.cbegin(); }
329
0
    auto end() const { return m_pubkey.cend(); }
330
331
    bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
332
0
    {
333
0
        return a.m_pubkey == b.m_pubkey;
334
0
    }
335
336
    bool friend operator!=(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
337
0
    {
338
0
        return a.m_pubkey != b.m_pubkey;
339
0
    }
340
};
341
342
struct CExtPubKey {
343
    unsigned char version[4];
344
    unsigned char nDepth;
345
    unsigned char vchFingerprint[4];
346
    unsigned int nChild;
347
    ChainCode chaincode;
348
    CPubKey pubkey;
349
350
    friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
351
0
    {
352
0
        return a.nDepth == b.nDepth &&
  Branch (352:16): [True: 0, False: 0]
353
0
            memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
  Branch (353:13): [True: 0, False: 0]
354
0
            a.nChild == b.nChild &&
  Branch (354:13): [True: 0, False: 0]
355
0
            a.chaincode == b.chaincode &&
  Branch (355:13): [True: 0, False: 0]
356
0
            a.pubkey == b.pubkey;
  Branch (356:13): [True: 0, False: 0]
357
0
    }
358
359
    friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
360
0
    {
361
0
        return !(a == b);
362
0
    }
363
364
    friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
365
0
    {
366
0
        if (a.pubkey < b.pubkey) {
  Branch (366:13): [True: 0, False: 0]
367
0
            return true;
368
0
        } else if (a.pubkey > b.pubkey) {
  Branch (368:20): [True: 0, False: 0]
369
0
            return false;
370
0
        }
371
0
        return a.chaincode < b.chaincode;
372
0
    }
373
374
    void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
375
    void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
376
    void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const;
377
    void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]);
378
    [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild) const;
379
};
380
381
#endif // BITCOIN_PUBKEY_H