Browse Source

add bip32 pubkey serialization

CExtPubKey should be serializable like CPubKey
0.13
Jonas Schnelli 10 years ago committed by Jonas Schnelli
parent
commit
90604f16af
No known key found for this signature in database
GPG Key ID: 29D4BCB6416F53EC
  1. 4
      src/base58.h
  2. 6
      src/key.cpp
  3. 21
      src/key.h
  4. 6
      src/pubkey.cpp
  5. 30
      src/pubkey.h
  6. 16
      src/test/bip32_tests.cpp

4
src/base58.h

@ -164,7 +164,7 @@ public:
CBitcoinExtKeyBase() {} CBitcoinExtKeyBase() {}
}; };
typedef CBitcoinExtKeyBase<CExtKey, 74, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey; typedef CBitcoinExtKeyBase<CExtKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
typedef CBitcoinExtKeyBase<CExtPubKey, 74, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey; typedef CBitcoinExtKeyBase<CExtPubKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
#endif // BITCOIN_BASE58_H #endif // BITCOIN_BASE58_H

6
src/key.cpp

@ -275,7 +275,7 @@ CExtPubKey CExtKey::Neuter() const {
return ret; return ret;
} }
void CExtKey::Encode(unsigned char code[74]) const { void CExtKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {
code[0] = nDepth; code[0] = nDepth;
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;
@ -286,12 +286,12 @@ void CExtKey::Encode(unsigned char code[74]) const {
memcpy(code+42, key.begin(), 32); memcpy(code+42, key.begin(), 32);
} }
void CExtKey::Decode(const unsigned char code[74]) { void CExtKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
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(chaincode.begin(), code+9, 32); memcpy(chaincode.begin(), code+9, 32);
key.Set(code+42, code+74, true); key.Set(code+42, code+BIP32_EXTKEY_SIZE, true);
} }
bool ECC_InitSanityCheck() { bool ECC_InitSanityCheck() {

21
src/key.h

@ -164,11 +164,28 @@ struct CExtKey {
a.chaincode == b.chaincode && a.key == b.key; a.chaincode == b.chaincode && a.key == b.key;
} }
void Encode(unsigned char code[74]) const; void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
void Decode(const unsigned char code[74]); void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtKey& out, unsigned int nChild) const; bool Derive(CExtKey& out, unsigned int nChild) const;
CExtPubKey Neuter() const; CExtPubKey Neuter() const;
void SetMaster(const unsigned char* seed, unsigned int nSeedLen); void SetMaster(const unsigned char* seed, unsigned int nSeedLen);
template <typename Stream>
void Serialize(Stream& s, int nType, int nVersion) const
{
unsigned int len = BIP32_EXTKEY_SIZE;
::WriteCompactSize(s, len);
unsigned char code[BIP32_EXTKEY_SIZE];
Encode(code);
s.write((const char *)&code[0], len);
}
template <typename Stream>
void Unserialize(Stream& s, int nType, int nVersion)
{
unsigned int len = ::ReadCompactSize(s);
unsigned char code[BIP32_EXTKEY_SIZE];
s.read((char *)&code[0], len);
Decode(code);
}
}; };
/** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */ /** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */

6
src/pubkey.cpp

@ -246,7 +246,7 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi
return true; return true;
} }
void CExtPubKey::Encode(unsigned char code[74]) const { void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {
code[0] = nDepth; code[0] = nDepth;
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;
@ -256,12 +256,12 @@ void CExtPubKey::Encode(unsigned char code[74]) const {
memcpy(code+41, pubkey.begin(), 33); memcpy(code+41, pubkey.begin(), 33);
} }
void CExtPubKey::Decode(const unsigned char code[74]) { void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
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(chaincode.begin(), code+9, 32); memcpy(chaincode.begin(), code+9, 32);
pubkey.Set(code+41, code+74); pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE);
} }
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {

30
src/pubkey.h

@ -23,6 +23,8 @@
* script supports up to 75 for single byte push * script supports up to 75 for single byte push
*/ */
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
{ {
@ -205,9 +207,33 @@ struct CExtPubKey {
a.chaincode == b.chaincode && a.pubkey == b.pubkey; a.chaincode == b.chaincode && a.pubkey == b.pubkey;
} }
void Encode(unsigned char code[74]) const; void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
void Decode(const unsigned char code[74]); void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtPubKey& out, unsigned int nChild) const; bool Derive(CExtPubKey& out, unsigned int nChild) const;
unsigned int GetSerializeSize(int nType, int nVersion) const
{
return BIP32_EXTKEY_SIZE+1; //add one byte for the size (compact int)
}
template <typename Stream>
void Serialize(Stream& s, int nType, int nVersion) const
{
unsigned int len = BIP32_EXTKEY_SIZE;
::WriteCompactSize(s, len);
unsigned char code[BIP32_EXTKEY_SIZE];
Encode(code);
s.write((const char *)&code[0], len);
}
template <typename Stream>
void Unserialize(Stream& s, int nType, int nVersion)
{
unsigned int len = ::ReadCompactSize(s);
unsigned char code[BIP32_EXTKEY_SIZE];
if (len != BIP32_EXTKEY_SIZE)
throw std::runtime_error("Invalid extended key size\n");
s.read((char *)&code[0], len);
Decode(code);
}
}; };
/** Users of this module must hold an ECCVerifyHandle. The constructor and /** Users of this module must hold an ECCVerifyHandle. The constructor and

16
src/test/bip32_tests.cpp

@ -117,6 +117,22 @@ void RunTest(const TestVector &test) {
} }
key = keyNew; key = keyNew;
pubkey = pubkeyNew; pubkey = pubkeyNew;
CDataStream ssPub(SER_DISK, CLIENT_VERSION);
ssPub << pubkeyNew;
BOOST_CHECK(ssPub.size() == 75);
CDataStream ssPriv(SER_DISK, CLIENT_VERSION);
ssPriv << keyNew;
BOOST_CHECK(ssPriv.size() == 75);
CExtPubKey pubCheck;
CExtKey privCheck;
ssPub >> pubCheck;
ssPriv >> privCheck;
BOOST_CHECK(pubCheck == pubkeyNew);
BOOST_CHECK(privCheck == keyNew);
} }
} }

Loading…
Cancel
Save