Browse Source

Merge pull request #5162

d2e74c5 boost: moveonly: split CPubKey and friends to new files (Cory Fields)
78c228c boost: moveonly: move BIP32Hash to hash.h (Cory Fields)
900078a boost: moveonly: create eccryptoverify.h|cpp and move helper functions there (Cory Fields)
0.10
Wladimir J. van der Laan 10 years ago
parent
commit
73b82a3089
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 4
      src/Makefile.am
  2. 2
      src/alert.cpp
  3. 1
      src/base58.h
  4. 1
      src/bloom.cpp
  5. 2
      src/compressor.cpp
  6. 63
      src/eccryptoverify.cpp
  7. 19
      src/eccryptoverify.h
  8. 13
      src/hash.cpp
  9. 1
      src/hash.h
  10. 183
      src/key.cpp
  11. 185
      src/key.h
  12. 1
      src/keystore.h
  13. 131
      src/pubkey.cpp
  14. 206
      src/pubkey.h
  15. 5
      src/script/interpreter.cpp
  16. 2
      src/script/sigcache.cpp
  17. 1
      src/script/standard.cpp
  18. 4
      src/script/standard.h
  19. 1
      src/test/miner_tests.cpp
  20. 1
      src/test/sigopcount_tests.cpp
  21. 1
      src/wallet_ismine.cpp

4
src/Makefile.am

@ -86,6 +86,7 @@ BITCOIN_CORE_H = \ @@ -86,6 +86,7 @@ BITCOIN_CORE_H = \
core_io.h \
crypter.h \
db.h \
eccryptoverify.h \
ecwrapper.h \
hash.h \
init.h \
@ -101,6 +102,7 @@ BITCOIN_CORE_H = \ @@ -101,6 +102,7 @@ BITCOIN_CORE_H = \
noui.h \
pow.h \
protocol.h \
pubkey.h \
random.h \
rpcclient.h \
rpcprotocol.h \
@ -220,12 +222,14 @@ libbitcoin_common_a_SOURCES = \ @@ -220,12 +222,14 @@ libbitcoin_common_a_SOURCES = \
core/transaction.cpp \
core_read.cpp \
core_write.cpp \
eccryptoverify.cpp \
ecwrapper.cpp \
hash.cpp \
key.cpp \
keystore.cpp \
netbase.cpp \
protocol.cpp \
pubkey.cpp \
script/interpreter.cpp \
script/script.cpp \
script/sigcache.cpp \

2
src/alert.cpp

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
#include "chainparams.h"
#include "clientversion.h"
#include "key.h"
#include "pubkey.h"
#include "net.h"
#include "timedata.h"
#include "ui_interface.h"

1
src/base58.h

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
#include "chainparams.h"
#include "key.h"
#include "pubkey.h"
#include "script/script.h"
#include "script/standard.h"

1
src/bloom.cpp

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
#include "bloom.h"
#include "core/transaction.h"
#include "hash.h"
#include "script/script.h"
#include "script/standard.h"
#include "streams.h"

2
src/compressor.cpp

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
#include "compressor.h"
#include "hash.h"
#include "key.h"
#include "pubkey.h"
#include "script/standard.h"
bool CScriptCompressor::IsToKeyID(CKeyID &hash) const

63
src/eccryptoverify.cpp

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
#include "eccryptoverify.h"
namespace {
int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
while (c1len > c2len) {
if (*c1)
return 1;
c1++;
c1len--;
}
while (c2len > c1len) {
if (*c2)
return -1;
c2++;
c2len--;
}
while (c1len > 0) {
if (*c1 > *c2)
return 1;
if (*c2 > *c1)
return -1;
c1++;
c2++;
c1len--;
}
return 0;
}
/** Order of secp256k1's generator minus 1. */
const unsigned char vchMaxModOrder[32] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40
};
/** Half of the order of secp256k1's generator minus 1. */
const unsigned char vchMaxModHalfOrder[32] = {
0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D,
0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0
};
const unsigned char vchZero[1] = {0};
} // anon namespace
namespace eccrypto {
bool Check(const unsigned char *vch) {
return vch &&
CompareBigEndian(vch, 32, vchZero, 0) > 0 &&
CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0;
}
bool CheckSignatureElement(const unsigned char *vch, int len, bool half) {
return vch &&
CompareBigEndian(vch, len, vchZero, 0) > 0 &&
CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0;
}
} // namespace eccrypto

19
src/eccryptoverify.h

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_EC_CRYPTO_VERIFY_H
#define BITCOIN_EC_CRYPTO_VERIFY_H
#include <vector>
#include <cstdlib>
class uint256;
namespace eccrypto {
bool Check(const unsigned char *vch);
bool CheckSignatureElement(const unsigned char *vch, int len, bool half);
} // eccrypto namespace
#endif

13
src/hash.cpp

@ -63,3 +63,16 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char @@ -63,3 +63,16 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
return h1;
}
void BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64])
{
unsigned char num[4];
num[0] = (nChild >> 24) & 0xFF;
num[1] = (nChild >> 16) & 0xFF;
num[2] = (nChild >> 8) & 0xFF;
num[3] = (nChild >> 0) & 0xFF;
CHMAC_SHA512(chainCode, 32).Write(&header, 1)
.Write(data, 32)
.Write(num, 4)
.Finalize(output);
}

1
src/hash.h

@ -159,4 +159,5 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL @@ -159,4 +159,5 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
void BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
#endif // BITCOIN_HASH_H

183
src/key.cpp

@ -5,6 +5,8 @@ @@ -5,6 +5,8 @@
#include "key.h"
#include "crypto/sha2.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "random.h"
#ifdef USE_SECP256K1
@ -30,60 +32,10 @@ public: @@ -30,60 +32,10 @@ public:
static CSecp256k1Init instance_of_csecp256k1;
#endif
int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
while (c1len > c2len) {
if (*c1)
return 1;
c1++;
c1len--;
}
while (c2len > c1len) {
if (*c2)
return -1;
c2++;
c2len--;
}
while (c1len > 0) {
if (*c1 > *c2)
return 1;
if (*c2 > *c1)
return -1;
c1++;
c2++;
c1len--;
}
return 0;
}
/** Order of secp256k1's generator minus 1. */
const unsigned char vchMaxModOrder[32] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40
};
/** Half of the order of secp256k1's generator minus 1. */
const unsigned char vchMaxModHalfOrder[32] = {
0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D,
0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0
};
const unsigned char vchZero[1] = {0};
} // anon namespace
bool CKey::Check(const unsigned char *vch) {
return CompareBigEndian(vch, 32, vchZero, 0) > 0 &&
CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0;
}
bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) {
return CompareBigEndian(vch, len, vchZero, 0) > 0 &&
CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0;
return eccrypto::Check(vch);
}
void CKey::MakeNewKey(bool fCompressedIn) {
@ -216,88 +168,6 @@ bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { @@ -216,88 +168,6 @@ bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
return true;
}
bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
if (!IsValid())
return false;
#ifdef USE_SECP256K1
if (secp256k1_ecdsa_verify((const unsigned char*)&hash, 32, &vchSig[0], vchSig.size(), begin(), size()) != 1)
return false;
#else
CECKey key;
if (!key.SetPubKey(begin(), size()))
return false;
if (!key.Verify(hash, vchSig))
return false;
#endif
return true;
}
bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
if (vchSig.size() != 65)
return false;
int recid = (vchSig[0] - 27) & 3;
bool fComp = ((vchSig[0] - 27) & 4) != 0;
#ifdef USE_SECP256K1
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact((const unsigned char*)&hash, 32, &vchSig[1], (unsigned char*)begin(), &pubkeylen, fComp, recid))
return false;
assert((int)size() == pubkeylen);
#else
CECKey key;
if (!key.Recover(hash, &vchSig[1], recid))
return false;
std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, fComp);
Set(pubkey.begin(), pubkey.end());
#endif
return true;
}
bool CPubKey::IsFullyValid() const {
if (!IsValid())
return false;
#ifdef USE_SECP256K1
if (!secp256k1_ecdsa_pubkey_verify(begin(), size()))
return false;
#else
CECKey key;
if (!key.SetPubKey(begin(), size()))
return false;
#endif
return true;
}
bool CPubKey::Decompress() {
if (!IsValid())
return false;
#ifdef USE_SECP256K1
int clen = size();
int ret = secp256k1_ecdsa_pubkey_decompress((unsigned char*)begin(), &clen);
assert(ret);
assert(clen == (int)size());
#else
CECKey key;
if (!key.SetPubKey(begin(), size()))
return false;
std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, false);
Set(pubkey.begin(), pubkey.end());
#endif
return true;
}
void static BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]) {
unsigned char num[4];
num[0] = (nChild >> 24) & 0xFF;
num[1] = (nChild >> 16) & 0xFF;
num[2] = (nChild >> 8) & 0xFF;
num[3] = (nChild >> 0) & 0xFF;
CHMAC_SHA512(chainCode, 32).Write(&header, 1)
.Write(data, 32)
.Write(num, 4)
.Finalize(output);
}
bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
assert(IsValid());
assert(IsCompressed());
@ -324,27 +194,6 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild @@ -324,27 +194,6 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild
return ret;
}
bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
assert(IsValid());
assert((nChild >> 31) == 0);
assert(begin() + 33 == end());
unsigned char out[64];
BIP32Hash(cc, nChild, *begin(), begin()+1, out);
memcpy(ccChild, out+32, 32);
#ifdef USE_SECP256K1
pubkeyChild = *this;
bool ret = secp256k1_ecdsa_pubkey_tweak_add((unsigned char*)pubkeyChild.begin(), pubkeyChild.size(), out);
#else
CECKey key;
bool ret = key.SetPubKey(begin(), size());
ret &= key.TweakPublic(out);
std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, true);
pubkeyChild.Set(pubkey.begin(), pubkey.end());
#endif
return ret;
}
bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
out.nDepth = nDepth + 1;
CKeyID id = key.GetPubKey().GetID();
@ -395,32 +244,6 @@ void CExtKey::Decode(const unsigned char code[74]) { @@ -395,32 +244,6 @@ void CExtKey::Decode(const unsigned char code[74]) {
key.Set(code+42, code+74, true);
}
void CExtPubKey::Encode(unsigned char code[74]) const {
code[0] = nDepth;
memcpy(code+1, vchFingerprint, 4);
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
memcpy(code+9, vchChainCode, 32);
assert(pubkey.size() == 33);
memcpy(code+41, pubkey.begin(), 33);
}
void CExtPubKey::Decode(const unsigned char code[74]) {
nDepth = code[0];
memcpy(vchFingerprint, code+1, 4);
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
memcpy(vchChainCode, code+9, 32);
pubkey.Set(code+41, code+74);
}
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
out.nDepth = nDepth + 1;
CKeyID id = pubkey.GetID();
memcpy(&out.vchFingerprint[0], &id, 4);
out.nChild = nChild;
return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode);
}
bool ECC_InitSanityCheck() {
#ifdef USE_SECP256K1
return true;

185
src/key.h

@ -7,13 +7,15 @@ @@ -7,13 +7,15 @@
#define BITCOIN_KEY_H
#include "allocators.h"
#include "hash.h"
#include "serialize.h"
#include "uint256.h"
#include <stdexcept>
#include <vector>
class CPubKey;
class CExtPubKey;
/**
* secp256k1:
* const unsigned int PRIVATE_KEY_SIZE = 279;
@ -24,169 +26,6 @@ @@ -24,169 +26,6 @@
* 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(const uint160& in) : uint160(in) {}
};
/** An encapsulated public key. */
class CPubKey
{
private:
/**
* Just store the serialized data.
* Its length can very cheaply be computed from the first byte.
*/
unsigned char vch[65];
//! 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;
if (chHeader == 4 || chHeader == 6 || chHeader == 7)
return 65;
return 0;
}
//! Set this key data to be invalid
void Invalidate()
{
vch[0] = 0xFF;
}
public:
//! Construct an invalid public key.
CPubKey()
{
Invalidate();
}
//! Initialize a public key using begin/end iterators to byte data.
template <typename T>
void Set(const T pbegin, const T pend)
{
int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
if (len && len == (pend - pbegin))
memcpy(vch, (unsigned char*)&pbegin[0], len);
else
Invalidate();
}
//! Construct a public key using begin/end iterators to byte data.
template <typename T>
CPubKey(const T pbegin, const T pend)
{
Set(pbegin, pend);
}
//! Construct a public key from a byte vector.
CPubKey(const std::vector<unsigned char>& vch)
{
Set(vch.begin(), vch.end());
}
//! Simple read-only vector-like interface to the pubkey data.
unsigned int size() const { return GetLen(vch[0]); }
const unsigned char* begin() const { return vch; }
const unsigned char* end() const { return vch + size(); }
const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
//! Comparator implementation.
friend bool operator==(const CPubKey& a, const CPubKey& b)
{
return a.vch[0] == b.vch[0] &&
memcmp(a.vch, b.vch, a.size()) == 0;
}
friend bool operator!=(const CPubKey& a, const CPubKey& b)
{
return !(a == b);
}
friend bool operator<(const CPubKey& a, const CPubKey& b)
{
return a.vch[0] < b.vch[0] ||
(a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
}
//! Implement serialization, as if this was a byte vector.
unsigned int GetSerializeSize(int nType, int nVersion) const
{
return size() + 1;
}
template <typename Stream>
void Serialize(Stream& s, int nType, int nVersion) const
{
unsigned int len = size();
::WriteCompactSize(s, len);
s.write((char*)vch, len);
}
template <typename Stream>
void Unserialize(Stream& s, int nType, int nVersion)
{
unsigned int len = ::ReadCompactSize(s);
if (len <= 65) {
s.read((char*)vch, len);
} else {
// invalid pubkey, skip available data
char dummy;
while (len--)
s.read(&dummy, 1);
Invalidate();
}
}
//! Get the KeyID of this public key (hash of its serialization)
CKeyID GetID() const
{
return CKeyID(Hash160(vch, vch + size()));
}
//! Get the 256-bit hash of this public key.
uint256 GetHash() const
{
return Hash(vch, vch + size());
}
/*
* Check syntactic correctness.
*
* Note that this is consensus critical as CheckSig() calls it!
*/
bool IsValid() const
{
return size() > 0;
}
//! fully validate whether this is a valid public key (more expensive than IsValid())
bool IsFullyValid() const;
//! Check whether this is a compressed public key.
bool IsCompressed() const
{
return size() == 33;
}
/**
* Verify a DER signature (~72 bytes).
* If this public key is not fully valid, the return value will be false.
*/
bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
//! Recover a public key from a compact signature.
bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
//! Turn this public key into an uncompressed public key.
bool Decompress();
//! Derive BIP32 child pubkey.
bool Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
};
/**
* secure_allocator is defined in allocators.h
* CPrivKey is a serialized private key, with all parameters included (279 bytes)
@ -304,24 +143,6 @@ public: @@ -304,24 +143,6 @@ public:
static bool CheckSignatureElement(const unsigned char* vch, int len, bool half);
};
struct CExtPubKey {
unsigned char nDepth;
unsigned char vchFingerprint[4];
unsigned int nChild;
unsigned char vchChainCode[32];
CPubKey pubkey;
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;
}
void Encode(unsigned char code[74]) const;
void Decode(const unsigned char code[74]);
bool Derive(CExtPubKey& out, unsigned int nChild) const;
};
struct CExtKey {
unsigned char nDepth;
unsigned char vchFingerprint[4];

1
src/keystore.h

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
#define BITCOIN_KEYSTORE_H
#include "key.h"
#include "pubkey.h"
#include "sync.h"
#include <boost/signals2/signal.hpp>

131
src/pubkey.cpp

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "pubkey.h"
#include "crypto/sha2.h"
#include "eccryptoverify.h"
#ifdef USE_SECP256K1
#include <secp256k1.h>
#else
#include "ecwrapper.h"
#endif
bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
if (!IsValid())
return false;
#ifdef USE_SECP256K1
if (secp256k1_ecdsa_verify((const unsigned char*)&hash, 32, &vchSig[0], vchSig.size(), begin(), size()) != 1)
return false;
#else
CECKey key;
if (!key.SetPubKey(begin(), size()))
return false;
if (!key.Verify(hash, vchSig))
return false;
#endif
return true;
}
bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
if (vchSig.size() != 65)
return false;
int recid = (vchSig[0] - 27) & 3;
bool fComp = ((vchSig[0] - 27) & 4) != 0;
#ifdef USE_SECP256K1
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact((const unsigned char*)&hash, 32, &vchSig[1], (unsigned char*)begin(), &pubkeylen, fComp, recid))
return false;
assert((int)size() == pubkeylen);
#else
CECKey key;
if (!key.Recover(hash, &vchSig[1], recid))
return false;
std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, fComp);
Set(pubkey.begin(), pubkey.end());
#endif
return true;
}
bool CPubKey::IsFullyValid() const {
if (!IsValid())
return false;
#ifdef USE_SECP256K1
if (!secp256k1_ecdsa_pubkey_verify(begin(), size()))
return false;
#else
CECKey key;
if (!key.SetPubKey(begin(), size()))
return false;
#endif
return true;
}
bool CPubKey::Decompress() {
if (!IsValid())
return false;
#ifdef USE_SECP256K1
int clen = size();
int ret = secp256k1_ecdsa_pubkey_decompress((unsigned char*)begin(), &clen);
assert(ret);
assert(clen == (int)size());
#else
CECKey key;
if (!key.SetPubKey(begin(), size()))
return false;
std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, false);
Set(pubkey.begin(), pubkey.end());
#endif
return true;
}
bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
assert(IsValid());
assert((nChild >> 31) == 0);
assert(begin() + 33 == end());
unsigned char out[64];
BIP32Hash(cc, nChild, *begin(), begin()+1, out);
memcpy(ccChild, out+32, 32);
#ifdef USE_SECP256K1
pubkeyChild = *this;
bool ret = secp256k1_ecdsa_pubkey_tweak_add((unsigned char*)pubkeyChild.begin(), pubkeyChild.size(), out);
#else
CECKey key;
bool ret = key.SetPubKey(begin(), size());
ret &= key.TweakPublic(out);
std::vector<unsigned char> pubkey;
key.GetPubKey(pubkey, true);
pubkeyChild.Set(pubkey.begin(), pubkey.end());
#endif
return ret;
}
void CExtPubKey::Encode(unsigned char code[74]) const {
code[0] = nDepth;
memcpy(code+1, vchFingerprint, 4);
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
memcpy(code+9, vchChainCode, 32);
assert(pubkey.size() == 33);
memcpy(code+41, pubkey.begin(), 33);
}
void CExtPubKey::Decode(const unsigned char code[74]) {
nDepth = code[0];
memcpy(vchFingerprint, code+1, 4);
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
memcpy(vchChainCode, code+9, 32);
pubkey.Set(code+41, code+74);
}
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
out.nDepth = nDepth + 1;
CKeyID id = pubkey.GetID();
memcpy(&out.vchFingerprint[0], &id, 4);
out.nChild = nChild;
return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode);
}

206
src/pubkey.h

@ -0,0 +1,206 @@ @@ -0,0 +1,206 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_PUBKEY_H
#define BITCOIN_PUBKEY_H
#include "hash.h"
#include "serialize.h"
#include "uint256.h"
#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(const uint160& in) : uint160(in) {}
};
/** An encapsulated public key. */
class CPubKey
{
private:
/**
* Just store the serialized data.
* Its length can very cheaply be computed from the first byte.
*/
unsigned char vch[65];
//! 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;
if (chHeader == 4 || chHeader == 6 || chHeader == 7)
return 65;
return 0;
}
//! Set this key data to be invalid
void Invalidate()
{
vch[0] = 0xFF;
}
public:
//! Construct an invalid public key.
CPubKey()
{
Invalidate();
}
//! Initialize a public key using begin/end iterators to byte data.
template <typename T>
void Set(const T pbegin, const T pend)
{
int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
if (len && len == (pend - pbegin))
memcpy(vch, (unsigned char*)&pbegin[0], len);
else
Invalidate();
}
//! Construct a public key using begin/end iterators to byte data.
template <typename T>
CPubKey(const T pbegin, const T pend)
{
Set(pbegin, pend);
}
//! Construct a public key from a byte vector.
CPubKey(const std::vector<unsigned char>& vch)
{
Set(vch.begin(), vch.end());
}
//! Simple read-only vector-like interface to the pubkey data.
unsigned int size() const { return GetLen(vch[0]); }
const unsigned char* begin() const { return vch; }
const unsigned char* end() const { return vch + size(); }
const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
//! Comparator implementation.
friend bool operator==(const CPubKey& a, const CPubKey& b)
{
return a.vch[0] == b.vch[0] &&
memcmp(a.vch, b.vch, a.size()) == 0;
}
friend bool operator!=(const CPubKey& a, const CPubKey& b)
{
return !(a == b);
}
friend bool operator<(const CPubKey& a, const CPubKey& b)
{
return a.vch[0] < b.vch[0] ||
(a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
}
//! Implement serialization, as if this was a byte vector.
unsigned int GetSerializeSize(int nType, int nVersion) const
{
return size() + 1;
}
template <typename Stream>
void Serialize(Stream& s, int nType, int nVersion) const
{
unsigned int len = size();
::WriteCompactSize(s, len);
s.write((char*)vch, len);
}
template <typename Stream>
void Unserialize(Stream& s, int nType, int nVersion)
{
unsigned int len = ::ReadCompactSize(s);
if (len <= 65) {
s.read((char*)vch, len);
} else {
// invalid pubkey, skip available data
char dummy;
while (len--)
s.read(&dummy, 1);
Invalidate();
}
}
//! Get the KeyID of this public key (hash of its serialization)
CKeyID GetID() const
{
return CKeyID(Hash160(vch, vch + size()));
}
//! Get the 256-bit hash of this public key.
uint256 GetHash() const
{
return Hash(vch, vch + size());
}
/*
* Check syntactic correctness.
*
* Note that this is consensus critical as CheckSig() calls it!
*/
bool IsValid() const
{
return size() > 0;
}
//! fully validate whether this is a valid public key (more expensive than IsValid())
bool IsFullyValid() const;
//! Check whether this is a compressed public key.
bool IsCompressed() const
{
return size() == 33;
}
/**
* Verify a DER signature (~72 bytes).
* If this public key is not fully valid, the return value will be false.
*/
bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
//! Recover a public key from a compact signature.
bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
//! Turn this public key into an uncompressed public key.
bool Decompress();
//! Derive BIP32 child pubkey.
bool Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
};
struct CExtPubKey {
unsigned char nDepth;
unsigned char vchFingerprint[4];
unsigned int nChild;
unsigned char vchChainCode[32];
CPubKey pubkey;
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;
}
void Encode(unsigned char code[74]) const;
void Decode(const unsigned char code[74]);
bool Derive(CExtPubKey& out, unsigned int nChild) const;
};
#endif // BITCOIN_PUBKEY_H

5
src/script/interpreter.cpp

@ -9,7 +9,8 @@ @@ -9,7 +9,8 @@
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha2.h"
#include "key.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "script/script.h"
#include "uint256.h"
#include "util.h"
@ -122,7 +123,7 @@ bool static IsLowDERSignature(const valtype &vchSig) { @@ -122,7 +123,7 @@ bool static IsLowDERSignature(const valtype &vchSig) {
// If the S value is above the order of the curve divided by two, its
// complement modulo the order could have been used instead, which is
// one byte shorter when encoded correctly.
if (!CKey::CheckSignatureElement(S, nLenS, true))
if (!eccrypto::CheckSignatureElement(S, nLenS, true))
return error("Non-canonical signature: S value is unnecessarily high");
return true;

2
src/script/sigcache.cpp

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
#include "sigcache.h"
#include "key.h"
#include "pubkey.h"
#include "random.h"
#include "uint256.h"
#include "util.h"

1
src/script/standard.cpp

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
#include "script/standard.h"
#include "pubkey.h"
#include "script/script.h"
#include "util.h"
#include "utilstrencodings.h"

4
src/script/standard.h

@ -6,8 +6,7 @@ @@ -6,8 +6,7 @@
#ifndef H_BITCOIN_SCRIPT_STANDARD
#define H_BITCOIN_SCRIPT_STANDARD
#include "key.h"
#include "script/script.h"
#include "uint256.h"
#include "script/interpreter.h"
#include <boost/variant.hpp>
@ -15,6 +14,7 @@ @@ -15,6 +14,7 @@
#include <stdint.h>
class CScript;
class CKeyID;
/** A reference to a CScript: the Hash160 of its serialization (see script.h) */
class CScriptID : public uint160

1
src/test/miner_tests.cpp

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
#include "main.h"
#include "miner.h"
#include "pubkey.h"
#include "uint256.h"
#include "util.h"

1
src/test/sigopcount_tests.cpp

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "pubkey.h"
#include "key.h"
#include "script/script.h"
#include "script/standard.h"

1
src/wallet_ismine.cpp

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
#include "key.h"
#include "keystore.h"
#include "script/script.h"
#include "script/standard.h"
#include <boost/foreach.hpp>

Loading…
Cancel
Save