// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2017 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <stdexcept>
#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
- */
-
/** A reference to a CKey: the Hash160 of its serialized public key */
class CKeyID : public uint160
{
public:
- CKeyID() : uint160(0) {}
+ CKeyID() : uint160() {}
CKeyID(const uint160& in) : uint160(in) {}
};
+typedef uint256 ChainCode;
+
/** An encapsulated public key. */
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:
/**
* Just store the serialized data.
* Its length can very cheaply be computed from the first byte.
*/
- unsigned char vch[65];
+ unsigned char vch[PUBLIC_KEY_SIZE];
//! Compute the length of a pubkey with a given first byte.
unsigned int static GetLen(unsigned char chHeader)
{
if (chHeader == 2 || chHeader == 3)
- return 33;
+ return COMPRESSED_PUBLIC_KEY_SIZE;
if (chHeader == 4 || chHeader == 6 || chHeader == 7)
- return 65;
+ return PUBLIC_KEY_SIZE;
return 0;
}
void Unserialize(Stream& s, int nType, int nVersion)
{
unsigned int len = ::ReadCompactSize(s);
- if (len <= 65) {
+ if (len <= PUBLIC_KEY_SIZE) {
s.read((char*)vch, len);
} else {
// invalid pubkey, skip available data
//! Check whether this is a compressed public key.
bool IsCompressed() const
{
- return size() == 33;
+ return size() == COMPRESSED_PUBLIC_KEY_SIZE;
}
/**
*/
bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
+ /**
+ * Check whether a signature is normalized (lower-S).
+ */
+ static bool CheckLowS(const std::vector<unsigned char>& vchSig);
+
//! Recover a public key from a compact signature.
bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
bool Decompress();
//! Derive BIP32 child pubkey.
- bool Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
+ bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
};
struct CExtPubKey {
unsigned char nDepth;
unsigned char vchFingerprint[4];
unsigned int nChild;
- unsigned char vchChainCode[32];
+ ChainCode chaincode;
CPubKey pubkey;
- friend bool operator==(const CExtPubKey& a, const CExtPubKey& b)
+ friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
{
return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild &&
- memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.pubkey == b.pubkey;
+ a.chaincode == b.chaincode && a.pubkey == b.pubkey;
}
void Encode(unsigned char code[74]) const;
bool Derive(CExtPubKey& out, unsigned int nChild) const;
};
+/** Users of this module must hold an ECCVerifyHandle. The constructor and
+ * destructor of these are not allowed to run in parallel, though. */
+class ECCVerifyHandle
+{
+ static int refcount;
+
+public:
+ ECCVerifyHandle();
+ ~ECCVerifyHandle();
+};
+
#endif // BITCOIN_PUBKEY_H