Coverage Report

Created: 2026-10-07 13:27

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