Browse Source

Merge pull request #6034

a574899 chaincodes: abstract away more chaincode behavior [squashme] replace struct CCainCode with a typedef uint256 ChainCode (Cory Fields)
8cf1485 Abstract chaincodes into CChainCode (Pieter Wuille)
0.13
Wladimir J. van der Laan 10 years ago
parent
commit
6a877e870e
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 8
      src/hash.cpp
  2. 4
      src/hash.h
  3. 14
      src/key.cpp
  4. 10
      src/key.h
  5. 10
      src/pubkey.cpp
  6. 8
      src/pubkey.h

8
src/hash.cpp

@ -5,6 +5,7 @@
#include "hash.h" #include "hash.h"
#include "crypto/common.h" #include "crypto/common.h"
#include "crypto/hmac_sha512.h" #include "crypto/hmac_sha512.h"
#include "pubkey.h"
inline uint32_t ROTL32(uint32_t x, int8_t r) inline uint32_t ROTL32(uint32_t x, int8_t r)
@ -71,15 +72,12 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
return h1; return h1;
} }
void BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]) void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64])
{ {
unsigned char num[4]; unsigned char num[4];
num[0] = (nChild >> 24) & 0xFF; num[0] = (nChild >> 24) & 0xFF;
num[1] = (nChild >> 16) & 0xFF; num[1] = (nChild >> 16) & 0xFF;
num[2] = (nChild >> 8) & 0xFF; num[2] = (nChild >> 8) & 0xFF;
num[3] = (nChild >> 0) & 0xFF; num[3] = (nChild >> 0) & 0xFF;
CHMAC_SHA512(chainCode, 32).Write(&header, 1) CHMAC_SHA512(chainCode.begin(), chainCode.size()).Write(&header, 1).Write(data, 32).Write(num, 4).Finalize(output);
.Write(data, 32)
.Write(num, 4)
.Finalize(output);
} }

4
src/hash.h

@ -14,6 +14,8 @@
#include <vector> #include <vector>
typedef uint256 ChainCode;
/** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */ /** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */
class CHash256 { class CHash256 {
private: private:
@ -159,6 +161,6 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash); 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]); void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
#endif // BITCOIN_HASH_H #endif // BITCOIN_HASH_H

14
src/key.cpp

@ -111,7 +111,7 @@ bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
return VerifyPubKey(vchPubKey); return VerifyPubKey(vchPubKey);
} }
bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const { bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {
assert(IsValid()); assert(IsValid());
assert(IsCompressed()); assert(IsCompressed());
unsigned char out[64]; unsigned char out[64];
@ -124,7 +124,7 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild
assert(begin() + 32 == end()); assert(begin() + 32 == end());
BIP32Hash(cc, nChild, 0, begin(), out); BIP32Hash(cc, nChild, 0, begin(), out);
} }
memcpy(ccChild, out+32, 32); memcpy(ccChild.begin(), out+32, 32);
memcpy((unsigned char*)keyChild.begin(), begin(), 32); memcpy((unsigned char*)keyChild.begin(), begin(), 32);
bool ret = secp256k1_ec_privkey_tweak_add(secp256k1_context, (unsigned char*)keyChild.begin(), out); bool ret = secp256k1_ec_privkey_tweak_add(secp256k1_context, (unsigned char*)keyChild.begin(), out);
UnlockObject(out); UnlockObject(out);
@ -138,7 +138,7 @@ bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
CKeyID id = key.GetPubKey().GetID(); CKeyID id = key.GetPubKey().GetID();
memcpy(&out.vchFingerprint[0], &id, 4); memcpy(&out.vchFingerprint[0], &id, 4);
out.nChild = nChild; out.nChild = nChild;
return key.Derive(out.key, out.vchChainCode, nChild, vchChainCode); return key.Derive(out.key, out.chaincode, nChild, chaincode);
} }
void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) { void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
@ -147,7 +147,7 @@ void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
LockObject(out); LockObject(out);
CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out); CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out);
key.Set(&out[0], &out[32], true); key.Set(&out[0], &out[32], true);
memcpy(vchChainCode, &out[32], 32); memcpy(chaincode.begin(), &out[32], 32);
UnlockObject(out); UnlockObject(out);
nDepth = 0; nDepth = 0;
nChild = 0; nChild = 0;
@ -160,7 +160,7 @@ CExtPubKey CExtKey::Neuter() const {
memcpy(&ret.vchFingerprint[0], &vchFingerprint[0], 4); memcpy(&ret.vchFingerprint[0], &vchFingerprint[0], 4);
ret.nChild = nChild; ret.nChild = nChild;
ret.pubkey = key.GetPubKey(); ret.pubkey = key.GetPubKey();
memcpy(&ret.vchChainCode[0], &vchChainCode[0], 32); ret.chaincode = chaincode;
return ret; return ret;
} }
@ -169,7 +169,7 @@ void CExtKey::Encode(unsigned char code[74]) const {
memcpy(code+1, vchFingerprint, 4); memcpy(code+1, vchFingerprint, 4);
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
memcpy(code+9, vchChainCode, 32); memcpy(code+9, chaincode.begin(), 32);
code[41] = 0; code[41] = 0;
assert(key.size() == 32); assert(key.size() == 32);
memcpy(code+42, key.begin(), 32); memcpy(code+42, key.begin(), 32);
@ -179,7 +179,7 @@ void CExtKey::Decode(const unsigned char code[74]) {
nDepth = code[0]; nDepth = code[0];
memcpy(vchFingerprint, code+1, 4); memcpy(vchFingerprint, code+1, 4);
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
memcpy(vchChainCode, code+9, 32); memcpy(chaincode.begin(), code+9, 32);
key.Set(code+42, code+74, true); key.Set(code+42, code+74, true);
} }

10
src/key.h

@ -6,6 +6,7 @@
#ifndef BITCOIN_KEY_H #ifndef BITCOIN_KEY_H
#define BITCOIN_KEY_H #define BITCOIN_KEY_H
#include "pubkey.h"
#include "serialize.h" #include "serialize.h"
#include "support/allocators/secure.h" #include "support/allocators/secure.h"
#include "uint256.h" #include "uint256.h"
@ -13,9 +14,6 @@
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
class CPubKey;
struct CExtPubKey;
/** /**
* secp256k1: * secp256k1:
@ -138,7 +136,7 @@ public:
bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const; bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;
//! Derive BIP32 child key. //! Derive BIP32 child key.
bool Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const; bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
/** /**
* Verify thoroughly whether a private key and a public key match. * Verify thoroughly whether a private key and a public key match.
@ -157,13 +155,13 @@ struct CExtKey {
unsigned char nDepth; unsigned char nDepth;
unsigned char vchFingerprint[4]; unsigned char vchFingerprint[4];
unsigned int nChild; unsigned int nChild;
unsigned char vchChainCode[32]; ChainCode chaincode;
CKey key; CKey key;
friend bool operator==(const CExtKey& a, const CExtKey& b) friend bool operator==(const CExtKey& a, const CExtKey& b)
{ {
return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && 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.key == b.key; a.chaincode == b.chaincode && a.key == b.key;
} }
void Encode(unsigned char code[74]) const; void Encode(unsigned char code[74]) const;

10
src/pubkey.cpp

@ -54,13 +54,13 @@ bool CPubKey::Decompress() {
return true; return true;
} }
bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const { bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {
assert(IsValid()); assert(IsValid());
assert((nChild >> 31) == 0); assert((nChild >> 31) == 0);
assert(begin() + 33 == end()); assert(begin() + 33 == end());
unsigned char out[64]; unsigned char out[64];
BIP32Hash(cc, nChild, *begin(), begin()+1, out); BIP32Hash(cc, nChild, *begin(), begin()+1, out);
memcpy(ccChild, out+32, 32); memcpy(ccChild.begin(), out+32, 32);
CECKey key; CECKey key;
bool ret = key.SetPubKey(begin(), size()); bool ret = key.SetPubKey(begin(), size());
ret &= key.TweakPublic(out); ret &= key.TweakPublic(out);
@ -75,7 +75,7 @@ void CExtPubKey::Encode(unsigned char code[74]) const {
memcpy(code+1, vchFingerprint, 4); memcpy(code+1, vchFingerprint, 4);
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
memcpy(code+9, vchChainCode, 32); memcpy(code+9, chaincode.begin(), 32);
assert(pubkey.size() == 33); assert(pubkey.size() == 33);
memcpy(code+41, pubkey.begin(), 33); memcpy(code+41, pubkey.begin(), 33);
} }
@ -84,7 +84,7 @@ void CExtPubKey::Decode(const unsigned char code[74]) {
nDepth = code[0]; nDepth = code[0];
memcpy(vchFingerprint, code+1, 4); memcpy(vchFingerprint, code+1, 4);
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
memcpy(vchChainCode, code+9, 32); memcpy(chaincode.begin(), code+9, 32);
pubkey.Set(code+41, code+74); pubkey.Set(code+41, code+74);
} }
@ -93,5 +93,5 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
CKeyID id = pubkey.GetID(); CKeyID id = pubkey.GetID();
memcpy(&out.vchFingerprint[0], &id, 4); memcpy(&out.vchFingerprint[0], &id, 4);
out.nChild = nChild; out.nChild = nChild;
return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode); return pubkey.Derive(out.pubkey, out.chaincode, nChild, chaincode);
} }

8
src/pubkey.h

@ -31,6 +31,8 @@ public:
CKeyID(const uint160& in) : uint160(in) {} CKeyID(const uint160& in) : uint160(in) {}
}; };
typedef uint256 ChainCode;
/** An encapsulated public key. */ /** An encapsulated public key. */
class CPubKey class CPubKey
{ {
@ -182,20 +184,20 @@ public:
bool Decompress(); bool Decompress();
//! Derive BIP32 child pubkey. //! 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 { struct CExtPubKey {
unsigned char nDepth; unsigned char nDepth;
unsigned char vchFingerprint[4]; unsigned char vchFingerprint[4];
unsigned int nChild; unsigned int nChild;
unsigned char vchChainCode[32]; ChainCode chaincode;
CPubKey pubkey; 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 && 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; void Encode(unsigned char code[74]) const;

Loading…
Cancel
Save