Skip to content

Commit

Permalink
add bip32 pubkey serialization
Browse files Browse the repository at this point in the history
CExtPubKey should be serializable like CPubKey
  • Loading branch information
jonasschnelli committed Apr 14, 2016
1 parent e6a4d48 commit 90604f1
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 12 deletions.
4 changes: 2 additions & 2 deletions src/base58.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ template<typename K, int Size, CChainParams::Base58Type Type> class CBitcoinExtK
CBitcoinExtKeyBase() {}
};

typedef CBitcoinExtKeyBase<CExtKey, 74, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
typedef CBitcoinExtKeyBase<CExtPubKey, 74, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
typedef CBitcoinExtKeyBase<CExtKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
typedef CBitcoinExtKeyBase<CExtPubKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;

#endif // BITCOIN_BASE58_H
6 changes: 3 additions & 3 deletions src/key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ CExtPubKey CExtKey::Neuter() const {
return ret;
}

void CExtKey::Encode(unsigned char code[74]) const {
void CExtKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {
code[0] = nDepth;
memcpy(code+1, vchFingerprint, 4);
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
Expand All @@ -286,12 +286,12 @@ void CExtKey::Encode(unsigned char code[74]) const {
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];
memcpy(vchFingerprint, code+1, 4);
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
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() {
Expand Down
21 changes: 19 additions & 2 deletions src/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,28 @@ struct CExtKey {
a.chaincode == b.chaincode && a.key == b.key;
}

void Encode(unsigned char code[74]) const;
void Decode(const unsigned char code[74]);
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtKey& out, unsigned int nChild) const;
CExtPubKey Neuter() const;
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. */
Expand Down
6 changes: 3 additions & 3 deletions src/pubkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi
return true;
}

void CExtPubKey::Encode(unsigned char code[74]) const {
void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {
code[0] = nDepth;
memcpy(code+1, vchFingerprint, 4);
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
Expand All @@ -256,12 +256,12 @@ void CExtPubKey::Encode(unsigned char code[74]) const {
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];
memcpy(vchFingerprint, code+1, 4);
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
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 {
Expand Down
30 changes: 28 additions & 2 deletions src/pubkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
* 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 */
class CKeyID : public uint160
{
Expand Down Expand Up @@ -205,9 +207,33 @@ struct CExtPubKey {
a.chaincode == b.chaincode && a.pubkey == b.pubkey;
}

void Encode(unsigned char code[74]) const;
void Decode(const unsigned char code[74]);
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
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
Expand Down
16 changes: 16 additions & 0 deletions src/test/bip32_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,22 @@ void RunTest(const TestVector &test) {
}
key = keyNew;
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);
}
}

Expand Down

0 comments on commit 90604f1

Please sign in to comment.