Changeset View
Changeset View
Standalone View
Standalone View
src/pubkey.h
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Copyright (c) 2017 The Zcash developers | |||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#ifndef BITCOIN_PUBKEY_H | #ifndef BITCOIN_PUBKEY_H | ||||
#define BITCOIN_PUBKEY_H | #define BITCOIN_PUBKEY_H | ||||
#include <hash.h> | #include <hash.h> | ||||
#include <serialize.h> | #include <serialize.h> | ||||
#include <uint256.h> | #include <uint256.h> | ||||
#include <boost/range/adaptor/sliced.hpp> | #include <boost/range/adaptor/sliced.hpp> | ||||
#include <stdexcept> | #include <stdexcept> | ||||
#include <vector> | #include <vector> | ||||
/** | |||||
* secp256k1: | |||||
* const unsigned int PRIVATE_KEY_SIZE = 279; | |||||
* const unsigned int PUBLIC_KEY_SIZE = 65; | |||||
* const unsigned int SIGNATURE_SIZE = 72; | |||||
* | |||||
* see www.keylength.com | |||||
* script supports up to 75 for single byte push | |||||
*/ | |||||
const unsigned int BIP32_EXTKEY_SIZE = 74; | const unsigned int BIP32_EXTKEY_SIZE = 74; | ||||
/** A reference to a CKey: the Hash160 of its serialized public key */ | /** A reference to a CKey: the Hash160 of its serialized public key */ | ||||
class CKeyID : public uint160 { | class CKeyID : public uint160 { | ||||
public: | public: | ||||
CKeyID() : uint160() {} | CKeyID() : uint160() {} | ||||
explicit CKeyID(const uint160 &in) : uint160(in) {} | explicit CKeyID(const uint160 &in) : uint160(in) {} | ||||
}; | }; | ||||
typedef uint256 ChainCode; | typedef uint256 ChainCode; | ||||
/** An encapsulated secp256k1 public key. */ | /** An encapsulated public key. */ | ||||
class CPubKey { | class CPubKey { | ||||
public: | |||||
/** | |||||
* secp256k1: | |||||
*/ | |||||
static const unsigned int PUBLIC_KEY_SIZE = 65; | |||||
static const unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33; | |||||
static const unsigned int SIGNATURE_SIZE = 72; | |||||
static const unsigned int COMPACT_SIGNATURE_SIZE = 65; | |||||
/** | |||||
* see www.keylength.com | |||||
* script supports up to 75 for single byte push | |||||
*/ | |||||
static_assert(PUBLIC_KEY_SIZE >= COMPRESSED_PUBLIC_KEY_SIZE, | |||||
"COMPRESSED_PUBLIC_KEY_SIZE is larger than PUBLIC_KEY_SIZE"); | |||||
private: | private: | ||||
/** | /** | ||||
* Just store the serialized data. | * Just store the serialized data. | ||||
* Its length can very cheaply be computed from the first byte. | * Its length can very cheaply be computed from the first byte. | ||||
*/ | */ | ||||
uint8_t vch[65]; | uint8_t vch[PUBLIC_KEY_SIZE]; | ||||
//! Compute the length of a pubkey with a given first byte. | //! Compute the length of a pubkey with a given first byte. | ||||
static unsigned int GetLen(uint8_t chHeader) { | static unsigned int GetLen(uint8_t chHeader) { | ||||
if (chHeader == 2 || chHeader == 3) { | if (chHeader == 2 || chHeader == 3) { | ||||
return 33; | return COMPRESSED_PUBLIC_KEY_SIZE; | ||||
} | } | ||||
if (chHeader == 4 || chHeader == 6 || chHeader == 7) { | if (chHeader == 4 || chHeader == 6 || chHeader == 7) { | ||||
return 65; | return PUBLIC_KEY_SIZE; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
//! Set this key data to be invalid | //! Set this key data to be invalid | ||||
void Invalidate() { vch[0] = 0xFF; } | void Invalidate() { vch[0] = 0xFF; } | ||||
public: | public: | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | public: | ||||
//! Implement serialization, as if this was a byte vector. | //! Implement serialization, as if this was a byte vector. | ||||
template <typename Stream> void Serialize(Stream &s) const { | template <typename Stream> void Serialize(Stream &s) const { | ||||
unsigned int len = size(); | unsigned int len = size(); | ||||
::WriteCompactSize(s, len); | ::WriteCompactSize(s, len); | ||||
s.write((char *)vch, len); | s.write((char *)vch, len); | ||||
} | } | ||||
template <typename Stream> void Unserialize(Stream &s) { | template <typename Stream> void Unserialize(Stream &s) { | ||||
unsigned int len = ::ReadCompactSize(s); | unsigned int len = ::ReadCompactSize(s); | ||||
if (len <= 65) { | if (len <= PUBLIC_KEY_SIZE) { | ||||
s.read((char *)vch, len); | s.read((char *)vch, len); | ||||
} else { | } else { | ||||
// invalid pubkey, skip available data | // invalid pubkey, skip available data | ||||
char dummy; | char dummy; | ||||
while (len--) { | while (len--) { | ||||
s.read(&dummy, 1); | s.read(&dummy, 1); | ||||
} | } | ||||
Invalidate(); | Invalidate(); | ||||
Show All 13 Lines | public: | ||||
*/ | */ | ||||
bool IsValid() const { return size() > 0; } | bool IsValid() const { return size() > 0; } | ||||
//! fully validate whether this is a valid public key (more expensive than | //! fully validate whether this is a valid public key (more expensive than | ||||
//! IsValid()) | //! IsValid()) | ||||
bool IsFullyValid() const; | bool IsFullyValid() const; | ||||
//! Check whether this is a compressed public key. | //! Check whether this is a compressed public key. | ||||
bool IsCompressed() const { return size() == 33; } | bool IsCompressed() const { return size() == COMPRESSED_PUBLIC_KEY_SIZE; } | ||||
/** | /** | ||||
* Verify a DER-serialized ECDSA signature (~72 bytes). | * Verify a DER-serialized ECDSA signature (~72 bytes). | ||||
* If this public key is not fully valid, the return value will be false. | * If this public key is not fully valid, the return value will be false. | ||||
*/ | */ | ||||
bool VerifyECDSA(const uint256 &hash, | bool VerifyECDSA(const uint256 &hash, | ||||
const std::vector<uint8_t> &vchSig) const; | const std::vector<uint8_t> &vchSig) const; | ||||
▲ Show 20 Lines • Show All 84 Lines • Show Last 20 Lines |