add bip32 pubkey serialization
CExtPubKey should be serializable like CPubKey
This commit is contained in:
parent
e6a4d48a9b
commit
90604f16af
6 changed files with 71 additions and 12 deletions
|
@ -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
|
||||||
|
|
|
@ -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
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. */
|
||||||
|
|
|
@ -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
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
|
||||||
|
|
|
@ -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…
Reference in a new issue