Implemented extended keys
This commit is contained in:
parent
0575840a9c
commit
0f67ca751e
5 changed files with 400 additions and 0 deletions
|
|
@ -341,6 +341,12 @@ target_link_libraries( bloom_test fc )
|
|||
add_executable( real128_test tests/all_tests.cpp tests/real128_test.cpp )
|
||||
target_link_libraries( real128_test fc )
|
||||
|
||||
add_executable( hmac_test tests/hmac_test.cpp )
|
||||
target_link_libraries( hmac_test fc )
|
||||
|
||||
add_executable( blinding_test tests/blinding_test.cpp )
|
||||
target_link_libraries( blinding_test fc )
|
||||
|
||||
|
||||
add_executable( udt_server tests/udts.cpp )
|
||||
target_link_libraries( udt_server fc udt )
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace fc {
|
|||
typedef fc::array<char,72> signature;
|
||||
typedef fc::array<unsigned char,65> compact_signature;
|
||||
typedef std::vector<char> range_proof_type;
|
||||
typedef fc::array<char,78> extended_key_data;
|
||||
|
||||
/**
|
||||
* @class public_key
|
||||
|
|
@ -73,6 +74,8 @@ namespace fc {
|
|||
static std::string to_base58( const public_key_data &key );
|
||||
static public_key from_base58( const std::string& b58 );
|
||||
|
||||
unsigned int fingerprint() const;
|
||||
|
||||
private:
|
||||
friend class private_key;
|
||||
static public_key from_key_data( const public_key_data& v );
|
||||
|
|
@ -136,13 +139,63 @@ namespace fc {
|
|||
return a.get_secret() < b.get_secret();
|
||||
}
|
||||
|
||||
unsigned int fingerprint() const { return get_public_key().fingerprint(); }
|
||||
|
||||
private:
|
||||
private_key( EC_KEY* k );
|
||||
static fc::sha256 get_secret( const EC_KEY * const k );
|
||||
fc::fwd<detail::private_key_impl,32> my;
|
||||
};
|
||||
|
||||
class extended_public_key : public public_key
|
||||
{
|
||||
public:
|
||||
extended_public_key( const public_key& k, const sha256& c,
|
||||
int child = 0, int parent_fp = 0, uint8_t depth = 0 );
|
||||
|
||||
extended_public_key derive_child( int i ) const;
|
||||
extended_public_key derive_normal_child( int i ) const;
|
||||
|
||||
extended_key_data serialize_extended() const;
|
||||
static extended_public_key deserialize( const extended_key_data& data );
|
||||
fc::string str() const;
|
||||
fc::string to_base58() const { return str(); }
|
||||
static extended_public_key from_base58( const fc::string& base58 );
|
||||
|
||||
private:
|
||||
sha256 c;
|
||||
int child_num, parent_fp;
|
||||
uint8_t depth;
|
||||
};
|
||||
|
||||
class extended_private_key : public private_key
|
||||
{
|
||||
public:
|
||||
extended_private_key( const private_key& k, const sha256& c,
|
||||
int child = 0, int parent_fp = 0, uint8_t depth = 0 );
|
||||
|
||||
extended_public_key get_extended_public_key()const;
|
||||
|
||||
extended_private_key derive_child( int i ) const;
|
||||
extended_private_key derive_normal_child( int i ) const;
|
||||
extended_private_key derive_hardened_child( int i ) const;
|
||||
|
||||
extended_key_data serialize_extended() const;
|
||||
static extended_private_key deserialize( const extended_key_data& data );
|
||||
fc::string str() const;
|
||||
fc::string to_base58() const { return str(); }
|
||||
static extended_private_key from_base58( const fc::string& base58 );
|
||||
static extended_private_key generate_master( const fc::string& seed );
|
||||
static extended_private_key generate_master( const char* seed, uint32_t seed_len );
|
||||
|
||||
private:
|
||||
extended_private_key private_derive_rest( const fc::sha512& hash,
|
||||
int num ) const;
|
||||
|
||||
sha256 c;
|
||||
int child_num, parent_fp;
|
||||
uint8_t depth;
|
||||
};
|
||||
|
||||
struct range_proof_info
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <fc/crypto/ripemd160.hpp>
|
||||
|
||||
/* stuff common to all ecc implementations */
|
||||
|
||||
|
|
@ -50,6 +51,14 @@ namespace fc { namespace ecc {
|
|||
return from_key_data(key);
|
||||
}
|
||||
|
||||
unsigned int public_key::fingerprint() const
|
||||
{
|
||||
public_key_data key = serialize();
|
||||
ripemd160 hash = ripemd160::hash( sha256::hash( key.begin(), key.size() ) );
|
||||
unsigned char* fp = (unsigned char*) hash._hash;
|
||||
return (fp[0] << 24) | (fp[1] << 16) | (fp[2] << 8) | fp[3];
|
||||
}
|
||||
|
||||
bool public_key::is_canonical( const compact_signature& c ) {
|
||||
return !(c.data[1] & 0x80)
|
||||
&& !(c.data[1] == 0 && !(c.data[2] & 0x80))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include <fc/crypto/elliptic.hpp>
|
||||
|
||||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/crypto/hmac.hpp>
|
||||
#include <fc/crypto/openssl.hpp>
|
||||
#include <fc/crypto/sha512.hpp>
|
||||
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
|
@ -12,6 +14,9 @@
|
|||
|
||||
#include "_elliptic_impl_priv.hpp"
|
||||
|
||||
#define BTC_EXT_PUB_MAGIC (0x0488B21E)
|
||||
#define BTC_EXT_PRIV_MAGIC (0x0488ADE4)
|
||||
|
||||
namespace fc { namespace ecc {
|
||||
namespace detail
|
||||
{
|
||||
|
|
@ -151,7 +156,229 @@ namespace fc { namespace ecc {
|
|||
FC_ASSERT( pk_len == my->_key.size() );
|
||||
}
|
||||
|
||||
static fc::sha256 _left( const fc::sha512& v )
|
||||
{
|
||||
fc::sha256 result;
|
||||
memcpy( result.data(), v.data(), 32 );
|
||||
return result;
|
||||
}
|
||||
|
||||
static fc::sha256 _right( const fc::sha512& v )
|
||||
{
|
||||
fc::sha256 result;
|
||||
memcpy( result.data(), v.data() + 32, 32 );
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef fc::array<char,37> chr37;
|
||||
|
||||
static void _put( unsigned char** dest, unsigned int i)
|
||||
{
|
||||
*(*dest)++ = (i >> 24) & 0xff;
|
||||
*(*dest)++ = (i >> 16) & 0xff;
|
||||
*(*dest)++ = (i >> 8) & 0xff;
|
||||
*(*dest)++ = i & 0xff;
|
||||
}
|
||||
|
||||
static unsigned int _get( unsigned char** src )
|
||||
{
|
||||
unsigned int result = *(*src)++ << 24;
|
||||
result |= *(*src)++ << 16;
|
||||
result |= *(*src)++ << 8;
|
||||
result |= *(*src)++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static chr37 _derive_message( char first, const char* key32, int i )
|
||||
{
|
||||
chr37 result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
*dest++ = first;
|
||||
memcpy( dest, key32, 32 ); dest += 32;
|
||||
_put( &dest, i );
|
||||
return result;
|
||||
}
|
||||
|
||||
static chr37 _derive_message( const public_key_data& key, int i )
|
||||
{
|
||||
return _derive_message( *key.begin(), key.begin() + 1, i );
|
||||
}
|
||||
|
||||
static chr37 _derive_message( const private_key_secret& key, int i )
|
||||
{
|
||||
return _derive_message( 0, key.data(), i );
|
||||
}
|
||||
|
||||
static fc::string _to_base58( const extended_key_data& key )
|
||||
{
|
||||
char buffer[key.size() + 4];
|
||||
memcpy( buffer, key.begin(), key.size() );
|
||||
fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( key.begin(), key.size() ));
|
||||
memcpy( buffer + key.size(), double_hash.data(), 4 );
|
||||
return fc::to_base58( buffer, sizeof(buffer) );
|
||||
}
|
||||
|
||||
static void _parse_extended_data( unsigned char* buffer, fc::string base58 )
|
||||
{
|
||||
memset( buffer, 0, 78 );
|
||||
std::vector<char> decoded = fc::from_base58( base58 );
|
||||
unsigned int i = 0;
|
||||
for ( char c : decoded )
|
||||
{
|
||||
if ( i >= 78 || i > decoded.size() - 4 ) { break; }
|
||||
buffer[i++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
typedef hmac<fc::sha512> hmac_sha512;
|
||||
|
||||
extended_public_key::extended_public_key( const public_key& k, const fc::sha256& c,
|
||||
int child, int parent, uint8_t depth )
|
||||
: public_key(k), c(c), child_num(child), parent_fp(parent), depth(depth) { }
|
||||
|
||||
extended_public_key extended_public_key::derive_child(int i) const
|
||||
{
|
||||
FC_ASSERT( !(i&0x80000000), "Can't derive hardened public key!" );
|
||||
return derive_normal_child(i);
|
||||
}
|
||||
|
||||
extended_public_key extended_public_key::derive_normal_child(int i) const
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
public_key_data key = serialize();
|
||||
const chr37 data = _derive_message( key, i );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
fc::sha256 left = _left(l);
|
||||
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) key.begin(), key.size(), (unsigned char*) left.data() ) > 0 );
|
||||
extended_public_key result( key, _right(l), i, fingerprint(), depth + 1 );
|
||||
return result;
|
||||
}
|
||||
|
||||
extended_key_data extended_public_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
_put( &dest, BTC_EXT_PUB_MAGIC );
|
||||
*dest++ = depth;
|
||||
_put( &dest, parent_fp );
|
||||
_put( &dest, child_num );
|
||||
memcpy( dest, c.data(), c.data_size() ); dest += 32;
|
||||
public_key_data key = serialize();
|
||||
memcpy( dest, key.begin(), key.size() );
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::string extended_public_key::str() const
|
||||
{
|
||||
return _to_base58( serialize_extended() );
|
||||
}
|
||||
|
||||
extended_public_key extended_public_key::from_base58( const fc::string& base58 )
|
||||
{
|
||||
unsigned char buffer[78];
|
||||
unsigned char* ptr = buffer;
|
||||
_parse_extended_data( buffer, base58 );
|
||||
FC_ASSERT( _get( &ptr ) == BTC_EXT_PUB_MAGIC, "Invalid extended private key" );
|
||||
uint8_t d = *ptr++;
|
||||
int fp = _get( &ptr );
|
||||
int cn = _get( &ptr );
|
||||
fc::sha256 chain;
|
||||
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
|
||||
public_key_data key;
|
||||
memcpy( key.begin(), ptr, key.size() );
|
||||
return extended_public_key( key, chain, cn, fp, d );
|
||||
}
|
||||
|
||||
extended_private_key::extended_private_key( const private_key& k, const sha256& c,
|
||||
int child, int parent, uint8_t depth )
|
||||
: private_key(k), c(c), child_num(child), parent_fp(parent), depth(depth) { }
|
||||
|
||||
extended_public_key extended_private_key::get_extended_public_key() const
|
||||
{
|
||||
return extended_public_key( get_public_key(), c, child_num, parent_fp, depth );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_child(int i) const
|
||||
{
|
||||
return i < 0 ? derive_hardened_child(i) : derive_normal_child(i);
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_normal_child(int i) const
|
||||
{
|
||||
const chr37 data = _derive_message( get_public_key().serialize(), i );
|
||||
hmac_sha512 mac;
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::derive_hardened_child(int i) const
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
private_key_secret key = get_secret();
|
||||
const chr37 data = _derive_message( key, i );
|
||||
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
|
||||
return private_derive_rest( l, i );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::private_derive_rest( const fc::sha512& hash,
|
||||
int i) const
|
||||
{
|
||||
fc::sha256 left = _left(hash);
|
||||
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) left.data(), (unsigned char*) get_secret().data() ) > 0 );
|
||||
extended_private_key result( private_key::regenerate( left ), _right(hash),
|
||||
i, fingerprint(), depth + 1 );
|
||||
return result;
|
||||
}
|
||||
|
||||
extended_key_data extended_private_key::serialize_extended() const
|
||||
{
|
||||
extended_key_data result;
|
||||
unsigned char* dest = (unsigned char*) result.begin();
|
||||
_put( &dest, BTC_EXT_PRIV_MAGIC );
|
||||
*dest++ = depth;
|
||||
_put( &dest, parent_fp );
|
||||
_put( &dest, child_num );
|
||||
memcpy( dest, c.data(), c.data_size() ); dest += 32;
|
||||
*dest++ = 0;
|
||||
private_key_secret key = get_secret();
|
||||
memcpy( dest, key.data(), key.data_size() );
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::string extended_private_key::str() const
|
||||
{
|
||||
return _to_base58( serialize_extended() );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::from_base58( const fc::string& base58 )
|
||||
{
|
||||
unsigned char buffer[78];
|
||||
unsigned char* ptr = buffer;
|
||||
_parse_extended_data( buffer, base58 );
|
||||
FC_ASSERT( _get( &ptr ) == BTC_EXT_PRIV_MAGIC, "Invalid extended private key" );
|
||||
uint8_t d = *ptr++;
|
||||
int fp = _get( &ptr );
|
||||
int cn = _get( &ptr );
|
||||
fc::sha256 chain;
|
||||
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
|
||||
ptr++;
|
||||
private_key_secret key;
|
||||
memcpy( key.data(), ptr, key.data_size() );
|
||||
return extended_private_key( private_key::regenerate(key), chain, cn, fp, d );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::generate_master( const fc::string& seed )
|
||||
{
|
||||
return generate_master( seed.c_str(), seed.size() );
|
||||
}
|
||||
|
||||
extended_private_key extended_private_key::generate_master( const char* seed, uint32_t seed_len )
|
||||
{
|
||||
hmac_sha512 mac;
|
||||
fc::sha512 hash = mac.digest( "Bitcoin seed", 12, seed, seed_len );
|
||||
extended_private_key result( private_key::regenerate( _left(hash) ), _right(hash) );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
commitment_type blind( const blind_factor_type& blind, uint64_t value )
|
||||
|
|
|
|||
105
tests/blinding_test.cpp
Normal file
105
tests/blinding_test.cpp
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
#define BOOST_TEST_MODULE BlindingTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <fc/array.hpp>
|
||||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
|
||||
// See https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Test_Vectors
|
||||
|
||||
static fc::string TEST1_SEED = "000102030405060708090a0b0c0d0e0f";
|
||||
static fc::string TEST1_M_PUB = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8";
|
||||
static fc::string TEST1_M_PRIV = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi";
|
||||
static fc::string TEST1_M_0H_PUB = "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw";
|
||||
static fc::string TEST1_M_0H_PRIV = "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7";
|
||||
static fc::string TEST1_M_0H_1_PUB = "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ";
|
||||
static fc::string TEST1_M_0H_1_PRIV = "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs";
|
||||
static fc::string TEST1_M_0H_1_2H_PUB = "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5";
|
||||
static fc::string TEST1_M_0H_1_2H_PRIV = "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM";
|
||||
static fc::string TEST1_M_0H_1_2H_2_PUB = "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV";
|
||||
static fc::string TEST1_M_0H_1_2H_2_PRIV = "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334";
|
||||
static fc::string TEST1_M_0H_1_2H_2_1g_PUB = "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy";
|
||||
static fc::string TEST1_M_0H_1_2H_2_1g_PRIV = "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76";
|
||||
|
||||
static fc::string TEST2_SEED = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542";
|
||||
static fc::string TEST2_M_PUB = "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB";
|
||||
static fc::string TEST2_M_PRIV = "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U";
|
||||
static fc::string TEST2_M_0_PUB = "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH";
|
||||
static fc::string TEST2_M_0_PRIV = "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt";
|
||||
static fc::string TEST2_M_0_m1_PUB = "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a";
|
||||
static fc::string TEST2_M_0_m1_PRIV = "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9";
|
||||
static fc::string TEST2_M_0_m1_1_PUB = "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon";
|
||||
static fc::string TEST2_M_0_m1_1_PRIV = "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef";
|
||||
static fc::string TEST2_M_0_m1_1_m2_PUB = "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL";
|
||||
static fc::string TEST2_M_0_m1_1_m2_PRIV = "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc";
|
||||
static fc::string TEST2_M_0_m1_1_m2_2_PUB = "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt";
|
||||
static fc::string TEST2_M_0_m1_1_m2_2_PRIV = "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j";
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_extended_keys_1)
|
||||
{
|
||||
char seed[16];
|
||||
fc::from_hex( TEST1_SEED, seed, sizeof(seed) );
|
||||
fc::ecc::extended_private_key master = fc::ecc::extended_private_key::generate_master( seed, sizeof(seed) );
|
||||
BOOST_CHECK_EQUAL( master.str(), TEST1_M_PRIV );
|
||||
BOOST_CHECK_EQUAL( master.get_extended_public_key().str(), TEST1_M_PUB );
|
||||
|
||||
BOOST_CHECK_EQUAL( fc::ecc::extended_private_key::from_base58(TEST1_M_PRIV).str(), TEST1_M_PRIV );
|
||||
BOOST_CHECK_EQUAL( fc::ecc::extended_public_key::from_base58(TEST1_M_PUB).str(), TEST1_M_PUB );
|
||||
BOOST_CHECK_EQUAL( fc::ecc::extended_private_key::from_base58(TEST1_M_0H_PRIV).str(), TEST1_M_0H_PRIV );
|
||||
BOOST_CHECK_EQUAL( fc::ecc::extended_public_key::from_base58(TEST1_M_0H_PUB).str(), TEST1_M_0H_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0 = master.derive_child(0x80000000);
|
||||
BOOST_CHECK_EQUAL( m_0.str(), TEST1_M_0H_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0.get_extended_public_key().str(), TEST1_M_0H_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_1 = m_0.derive_child(1);
|
||||
BOOST_CHECK_EQUAL( m_0_1.str(), TEST1_M_0H_1_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_1.get_extended_public_key().str(), TEST1_M_0H_1_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0.get_extended_public_key().derive_child(1).str(), TEST1_M_0H_1_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_1_2 = m_0_1.derive_child(0x80000002);
|
||||
BOOST_CHECK_EQUAL( m_0_1_2.str(), TEST1_M_0H_1_2H_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2.get_extended_public_key().str(), TEST1_M_0H_1_2H_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_1_2_2 = m_0_1_2.derive_child(2);
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2.str(), TEST1_M_0H_1_2H_2_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2.get_extended_public_key().str(), TEST1_M_0H_1_2H_2_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2.get_extended_public_key().derive_child(2).str(), TEST1_M_0H_1_2H_2_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_1_2_2_1g = m_0_1_2_2.derive_child(1000000000);
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2_1g.str(), TEST1_M_0H_1_2H_2_1g_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2_1g.get_extended_public_key().str(), TEST1_M_0H_1_2H_2_1g_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0_1_2_2.get_extended_public_key().derive_child(1000000000).str(), TEST1_M_0H_1_2H_2_1g_PUB );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_extended_keys_2)
|
||||
{
|
||||
char seed[64];
|
||||
fc::from_hex( TEST2_SEED, seed, sizeof(seed) );
|
||||
fc::ecc::extended_private_key master = fc::ecc::extended_private_key::generate_master( seed, sizeof(seed) );
|
||||
BOOST_CHECK_EQUAL( master.str(), TEST2_M_PRIV );
|
||||
BOOST_CHECK_EQUAL( master.get_extended_public_key().str(), TEST2_M_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0 = master.derive_child(0);
|
||||
BOOST_CHECK_EQUAL( m_0.str(), TEST2_M_0_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0.get_extended_public_key().str(), TEST2_M_0_PUB );
|
||||
BOOST_CHECK_EQUAL( master.get_extended_public_key().derive_child(0).str(), TEST2_M_0_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_m1 = m_0.derive_child(-1);
|
||||
BOOST_CHECK_EQUAL( m_0_m1.str(), TEST2_M_0_m1_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_m1.get_extended_public_key().str(), TEST2_M_0_m1_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_m1_1 = m_0_m1.derive_child(1);
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1.str(), TEST2_M_0_m1_1_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1.get_extended_public_key().str(), TEST2_M_0_m1_1_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0_m1.get_extended_public_key().derive_child(1).str(), TEST2_M_0_m1_1_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_m1_1_m2 = m_0_m1_1.derive_child(-2);
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2.str(), TEST2_M_0_m1_1_m2_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2.get_extended_public_key().str(), TEST2_M_0_m1_1_m2_PUB );
|
||||
|
||||
fc::ecc::extended_private_key m_0_m1_1_m2_2 = m_0_m1_1_m2.derive_child(2);
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2_2.str(), TEST2_M_0_m1_1_m2_2_PRIV );
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2_2.get_extended_public_key().str(), TEST2_M_0_m1_1_m2_2_PUB );
|
||||
BOOST_CHECK_EQUAL( m_0_m1_1_m2.get_extended_public_key().derive_child(2).str(), TEST2_M_0_m1_1_m2_2_PUB );
|
||||
}
|
||||
Loading…
Reference in a new issue