Return std::optional<CExtKey> from CExtKey::Master

Master key generation is fallible, but the type of master
key generation did not previously reflect that the generated
key might be invalid.
This commit is contained in:
Kris Nuttycombe 2022-03-11 18:47:01 -07:00
parent f6a8461047
commit 0c38ad9200
4 changed files with 10 additions and 5 deletions

View File

@ -290,7 +290,7 @@ std::optional<CExtKey> CExtKey::Derive(unsigned int _nChild) const {
} }
} }
CExtKey CExtKey::Master(const unsigned char *seed, unsigned int nSeedLen) { std::optional<CExtKey> CExtKey::Master(const unsigned char *seed, unsigned int nSeedLen) {
CExtKey xk; CExtKey xk;
static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'}; static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
std::vector<unsigned char, secure_allocator<unsigned char>> vout(64); std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);
@ -301,7 +301,11 @@ CExtKey CExtKey::Master(const unsigned char *seed, unsigned int nSeedLen) {
xk.nChild = 0; xk.nChild = 0;
memset(xk.vchFingerprint, 0, sizeof(xk.vchFingerprint)); memset(xk.vchFingerprint, 0, sizeof(xk.vchFingerprint));
if (xk.key.IsValid()) {
return xk; return xk;
} else {
return std::nullopt;
}
} }
CExtPubKey CExtKey::Neuter() const { CExtPubKey CExtKey::Neuter() const {

View File

@ -166,7 +166,7 @@ struct CExtKey {
a.key == b.key; a.key == b.key;
} }
static CExtKey Master(const unsigned char* seed, unsigned int nSeedLen); static std::optional<CExtKey> Master(const unsigned char* seed, unsigned int nSeedLen);
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const; void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);

View File

@ -80,7 +80,7 @@ TestVector test2 =
void RunTest(const TestVector &test) { void RunTest(const TestVector &test) {
std::vector<unsigned char> seed = ParseHex(test.strHexMaster); std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
CExtKey key = CExtKey::Master(&seed[0], seed.size()); CExtKey key = CExtKey::Master(&seed[0], seed.size()).value();
CExtPubKey pubkey = key.Neuter(); CExtPubKey pubkey = key.Neuter();
KeyIO keyIO(Params()); KeyIO keyIO(Params());
for (const TestDerivation &derive : test.vDerive) { for (const TestDerivation &derive : test.vDerive) {

View File

@ -74,10 +74,11 @@ std::optional<AccountKey> AccountKey::ForAccount(
AccountId accountId) { AccountId accountId) {
auto rawSeed = seed.RawSeed(); auto rawSeed = seed.RawSeed();
auto m = CExtKey::Master(rawSeed.data(), rawSeed.size()); auto m = CExtKey::Master(rawSeed.data(), rawSeed.size());
if (!m.has_value()) return std::nullopt;
// We use a fixed keypath scheme of m/44'/coin_type'/account' // We use a fixed keypath scheme of m/44'/coin_type'/account'
// Derive m/44' // Derive m/44'
auto m_44h = m.Derive(44 | HARDENED_KEY_LIMIT); auto m_44h = m.value().Derive(44 | HARDENED_KEY_LIMIT);
if (!m_44h.has_value()) return std::nullopt; if (!m_44h.has_value()) return std::nullopt;
// Derive m/44'/coin_type' // Derive m/44'/coin_type'