dash/src/hdchain.h
UdjinM6 27f3218de9 HD wallet (#1405)
* HD wallet

Minimal set of changes (no refactoring) backported from Bitcoin upstream to make HD wallets work in Dash 0.12.1.x+

* minimal bip44 (hardcoded account and change)

* minimal bip39

Additional cmd-line options for new wallet:
-mnemonic
-mnemonicpassphrase

* Do not recreate HD wallet on encryption

Adjusted keypool.py test

* Do not store any private keys for hd wallet besides the master one

Derive all keys on the fly.
Original idea/implementation - btc PR9298, backported and improved

* actually use bip39

* pbkdf2 test

* backport wallet-hd.py test

* Allow specifying hd seed, add dumphdseed rpc, fix bugs

- -hdseed cmd-line param to specify HD seed on wallet creation
- dumphdseed rpc to dump HD seed
- allow seed of any size
- fix dumpwallet rpc bug (wasn't decrypting HD seed)
- print HD seed and extended public masterkey on dumpwallet

* top up keypool on HD wallet encryption

* split HD chain: external/internal

* add missing cs_wallet lock in init.cpp

* fix `const char *` issues (use strings)

* default mnemonic passphrase is an empty string in all cases

* store mnemonic/mnemonicpassphrase

replace dumphdseed with dumphdinfo

* Add fCrypted flag to CHDChain

* prepare internal structures for multiple HD accounts

(plus some code cleanup)

* use secure allocator for storing sensitive HD data

* use secure strings for mnemonic(passphrase)

* small fix in GenerateNewHDChain

* use 24 words for mnemonic by default

* make sure mnemonic passphrase provided by user does not exceed 256 symbols

* more usage of secure allocators and memory_cleanse

* code cleanup

* rename: CSecureVector -> SecureVector

* add missing include

* fix warning in rpcdump.cpp

* refactor mnemonic_check (also fix a bug)

* move bip39 functions to CMnemonic

* Few fixes for CMnemonic:
- use `SecureVector` for data, bits, seed
- `Check` should return bool

* init vectors with desired size where possible
2017-05-29 14:51:40 +03:00

153 lines
4.4 KiB
C++

// Copyright (c) 2014-2017 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
#ifndef DASH_HDCHAIN_H
#define DASH_HDCHAIN_H
#include "key.h"
#include "sync.h"
/* hd account data model */
class CHDAccount
{
public:
uint32_t nExternalChainCounter;
uint32_t nInternalChainCounter;
CHDAccount() : nExternalChainCounter(0), nInternalChainCounter(0) {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
{
READWRITE(nExternalChainCounter);
READWRITE(nInternalChainCounter);
}
};
/* simple HD chain data model */
class CHDChain
{
private:
static const int CURRENT_VERSION = 1;
int nVersion;
uint256 id;
bool fCrypted;
SecureVector vchSeed;
SecureVector vchMnemonic;
SecureVector vchMnemonicPassphrase;
std::map<uint32_t, CHDAccount> mapAccounts;
// critical section to protect mapAccounts
mutable CCriticalSection cs_accounts;
public:
CHDChain() : nVersion(CHDChain::CURRENT_VERSION) { SetNull(); }
CHDChain(const CHDChain& other) :
nVersion(other.nVersion),
id(other.id),
fCrypted(other.fCrypted),
vchSeed(other.vchSeed),
vchMnemonic(other.vchMnemonic),
vchMnemonicPassphrase(other.vchMnemonicPassphrase),
mapAccounts(other.mapAccounts)
{}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
{
LOCK(cs_accounts);
READWRITE(this->nVersion);
nVersion = this->nVersion;
READWRITE(id);
READWRITE(fCrypted);
READWRITE(vchSeed);
READWRITE(vchMnemonic);
READWRITE(vchMnemonicPassphrase);
READWRITE(mapAccounts);
}
void swap(CHDChain& first, CHDChain& second) // nothrow
{
// enable ADL (not necessary in our case, but good practice)
using std::swap;
// by swapping the members of two classes,
// the two classes are effectively swapped
swap(first.nVersion, second.nVersion);
swap(first.id, second.id);
swap(first.fCrypted, second.fCrypted);
swap(first.vchSeed, second.vchSeed);
swap(first.vchMnemonic, second.vchMnemonic);
swap(first.vchMnemonicPassphrase, second.vchMnemonicPassphrase);
swap(first.mapAccounts, second.mapAccounts);
}
CHDChain& operator=(CHDChain from)
{
swap(*this, from);
return *this;
}
bool SetNull();
bool IsNull() const;
void SetCrypted(bool fCryptedIn);
bool IsCrypted() const;
void Debug(std::string strName) const;
bool SetMnemonic(const SecureVector& vchMnemonic, const SecureVector& vchMnemonicPassphrase, bool fUpdateID);
bool SetMnemonic(const SecureString& ssMnemonic, const SecureString& ssMnemonicPassphrase, bool fUpdateID);
bool GetMnemonic(SecureVector& vchMnemonicRet, SecureVector& vchMnemonicPassphraseRet) const;
bool GetMnemonic(SecureString& ssMnemonicRet, SecureString& ssMnemonicPassphraseRet) const;
bool SetSeed(const SecureVector& vchSeedIn, bool fUpdateID);
SecureVector GetSeed() const;
uint256 GetID() const { return id; }
uint256 GetSeedHash();
void DeriveChildExtKey(uint32_t nAccountIndex, bool fInternal, uint32_t nChildIndex, CExtKey& extKeyRet);
void AddAccount();
bool GetAccount(uint32_t nAccountIndex, CHDAccount& hdAccountRet);
bool SetAccount(uint32_t nAccountIndex, const CHDAccount& hdAccount);
size_t CountAccounts();
};
/* hd pubkey data model */
class CHDPubKey
{
private:
static const int CURRENT_VERSION = 1;
int nVersion;
public:
CExtPubKey extPubKey;
uint256 hdchainID;
uint32_t nAccountIndex;
uint32_t nChangeIndex;
CHDPubKey() : nVersion(CHDPubKey::CURRENT_VERSION), nAccountIndex(0), nChangeIndex(0) {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion)
{
READWRITE(this->nVersion);
nVersion = this->nVersion;
READWRITE(extPubKey);
READWRITE(hdchainID);
READWRITE(nAccountIndex);
READWRITE(nChangeIndex);
}
std::string GetKeyPath() const;
};
#endif // DASH_HDCHAIN_H