wallet: Store HDSeed and chain data
This commit is contained in:
parent
ec653523ad
commit
e2416930ea
|
@ -1865,6 +1865,92 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
|
|||
return nChange;
|
||||
}
|
||||
|
||||
bool CWallet::IsHDFullyEnabled() const
|
||||
{
|
||||
// Only Sapling addresses are HD for now
|
||||
return false;
|
||||
}
|
||||
|
||||
void CWallet::GenerateNewSeed()
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
|
||||
auto seed = HDSeed::Random(HD_WALLET_SEED_LENGTH);
|
||||
|
||||
int64_t nCreationTime = GetTime();
|
||||
|
||||
// If the wallet is encrypted and locked, this will fail.
|
||||
if (!SetHDSeed(seed))
|
||||
throw std::runtime_error(std::string(__func__) + ": SetHDSeed failed");
|
||||
|
||||
// store the key creation time together with
|
||||
// the child index counter in the database
|
||||
// as a hdchain object
|
||||
CHDChain newHdChain;
|
||||
newHdChain.nVersion = CHDChain::VERSION_HD_BASE;
|
||||
newHdChain.seedFp = seed.Fingerprint();
|
||||
newHdChain.nCreateTime = nCreationTime;
|
||||
SetHDChain(newHdChain, false);
|
||||
}
|
||||
|
||||
bool CWallet::SetHDSeed(const HDSeed& seed)
|
||||
{
|
||||
if (!CCryptoKeyStore::SetHDSeed(seed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fFileBacked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
if (!IsCrypted()) {
|
||||
return CWalletDB(strWalletFile).WriteHDSeed(seed);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::SetCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
if (!CCryptoKeyStore::SetCryptedHDSeed(seedFp, vchCryptedSecret)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fFileBacked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
if (pwalletdbEncryption)
|
||||
return pwalletdbEncryption->WriteCryptedHDSeed(seedFp, vchCryptedSecret);
|
||||
else
|
||||
return CWalletDB(strWalletFile).WriteCryptedHDSeed(seedFp, vchCryptedSecret);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CWallet::SetHDChain(const CHDChain& chain, bool memonly)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
if (!memonly && fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(chain))
|
||||
throw std::runtime_error(std::string(__func__) + ": writing chain failed");
|
||||
|
||||
hdChain = chain;
|
||||
}
|
||||
|
||||
bool CWallet::LoadHDSeed(const HDSeed& seed)
|
||||
{
|
||||
return CBasicKeyStore::SetHDSeed(seed);
|
||||
}
|
||||
|
||||
bool CWallet::LoadCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& seed)
|
||||
{
|
||||
return CCryptoKeyStore::SetCryptedHDSeed(seedFp, seed);
|
||||
}
|
||||
|
||||
void CWalletTx::SetSproutNoteData(mapSproutNoteData_t ¬eData)
|
||||
{
|
||||
mapSproutNoteData.clear();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "wallet/walletdb.h"
|
||||
#include "wallet/rpcwallet.h"
|
||||
#include "zcash/Address.hpp"
|
||||
#include "zcash/zip32.h"
|
||||
#include "base58.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -61,6 +62,9 @@ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
|
|||
// unless there is some exceptional network disruption.
|
||||
static const unsigned int WITNESS_CACHE_SIZE = MAX_REORG_LENGTH + 1;
|
||||
|
||||
//! Size of HD seed in bytes
|
||||
static const size_t HD_WALLET_SEED_LENGTH = 32;
|
||||
|
||||
class CBlockIndex;
|
||||
class CCoinControl;
|
||||
class COutput;
|
||||
|
@ -823,6 +827,9 @@ protected:
|
|||
bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx);
|
||||
void MarkAffectedTransactionsDirty(const CTransaction& tx);
|
||||
|
||||
/* the hd chain data model (chain counters) */
|
||||
CHDChain hdChain;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Main wallet lock.
|
||||
|
@ -1223,6 +1230,27 @@ public:
|
|||
/** Set whether this wallet broadcasts transactions. */
|
||||
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
|
||||
|
||||
/* Returns true if HD is enabled for all address types, false if only for Sapling */
|
||||
bool IsHDFullyEnabled() const;
|
||||
|
||||
/* Generates a new HD seed (will reset the chain child index counters)
|
||||
Sets the seed's version based on the current wallet version (so the
|
||||
caller must ensure the current wallet version is correct before calling
|
||||
this function). */
|
||||
void GenerateNewSeed();
|
||||
|
||||
bool SetHDSeed(const HDSeed& seed);
|
||||
bool SetCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
|
||||
/* Set the HD chain model (chain child index counters) */
|
||||
void SetHDChain(const CHDChain& chain, bool memonly);
|
||||
const CHDChain& GetHDChain() const { return hdChain; }
|
||||
|
||||
/* Set the current HD seed, without saving it to disk (used by LoadWallet) */
|
||||
bool LoadHDSeed(const HDSeed& key);
|
||||
/* Set the current encrypted HD seed, without saving it to disk (used by LoadWallet) */
|
||||
bool LoadCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& seed);
|
||||
|
||||
/* Find notes filtered by payment address, min depth, ability to spend */
|
||||
void GetFilteredNotes(std::vector<CSproutNotePlaintextEntry>& sproutEntries,
|
||||
std::vector<SaplingNoteEntry>& saplingEntries,
|
||||
|
|
|
@ -708,6 +708,45 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||
{
|
||||
ssValue >> pwallet->nWitnessCacheSize;
|
||||
}
|
||||
else if (strType == "hdseed")
|
||||
{
|
||||
uint256 seedFp;
|
||||
RawHDSeed rawSeed;
|
||||
ssKey >> seedFp;
|
||||
ssValue >> rawSeed;
|
||||
HDSeed seed(rawSeed);
|
||||
|
||||
if (seed.Fingerprint() != seedFp)
|
||||
{
|
||||
strErr = "Error reading wallet database: HDSeed corrupt";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pwallet->LoadHDSeed(seed))
|
||||
{
|
||||
strErr = "Error reading wallet database: LoadHDSeed failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (strType == "chdseed")
|
||||
{
|
||||
uint256 seedFp;
|
||||
vector<unsigned char> vchCryptedSecret;
|
||||
ssKey >> seedFp;
|
||||
ssValue >> vchCryptedSecret;
|
||||
if (!pwallet->LoadCryptedHDSeed(seedFp, vchCryptedSecret))
|
||||
{
|
||||
strErr = "Error reading wallet database: LoadCryptedSeed failed";
|
||||
return false;
|
||||
}
|
||||
wss.fIsEncrypted = true;
|
||||
}
|
||||
else if (strType == "hdchain")
|
||||
{
|
||||
CHDChain chain;
|
||||
ssValue >> chain;
|
||||
pwallet->SetHDChain(chain, true);
|
||||
}
|
||||
} catch (...)
|
||||
{
|
||||
return false;
|
||||
|
@ -718,6 +757,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||
static bool IsKeyType(string strType)
|
||||
{
|
||||
return (strType== "key" || strType == "wkey" ||
|
||||
strType == "hdseed" || strType == "chdseed" ||
|
||||
strType == "zkey" || strType == "czkey" ||
|
||||
strType == "vkey" ||
|
||||
strType == "mkey" || strType == "ckey");
|
||||
|
@ -1103,3 +1143,22 @@ bool CWalletDB::EraseDestData(const std::string &address, const std::string &key
|
|||
nWalletDBUpdated++;
|
||||
return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
||||
}
|
||||
|
||||
|
||||
bool CWalletDB::WriteHDSeed(const HDSeed& seed)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("hdseed"), seed.Fingerprint()), seed.RawSeed());
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& vchCryptedSecret)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("chdseed"), seedFp), vchCryptedSecret);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteHDChain(const CHDChain& chain)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::string("hdchain"), chain);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "key.h"
|
||||
#include "keystore.h"
|
||||
#include "zcash/Address.hpp"
|
||||
#include "zcash/zip32.h"
|
||||
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
|
@ -40,6 +41,39 @@ enum DBErrors
|
|||
DB_NEED_REWRITE
|
||||
};
|
||||
|
||||
/* simple hd chain data model */
|
||||
class CHDChain
|
||||
{
|
||||
public:
|
||||
static const int VERSION_HD_BASE = 1;
|
||||
static const int CURRENT_VERSION = VERSION_HD_BASE;
|
||||
int nVersion;
|
||||
uint256 seedFp;
|
||||
int64_t nCreateTime; // 0 means unknown
|
||||
uint32_t saplingAccountCounter;
|
||||
|
||||
CHDChain() { SetNull(); }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(nVersion);
|
||||
READWRITE(seedFp);
|
||||
READWRITE(nCreateTime);
|
||||
READWRITE(saplingAccountCounter);
|
||||
}
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
nVersion = CHDChain::CURRENT_VERSION;
|
||||
seedFp.SetNull();
|
||||
nCreateTime = 0;
|
||||
saplingAccountCounter = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CKeyMetadata
|
||||
{
|
||||
public:
|
||||
|
@ -132,6 +166,11 @@ public:
|
|||
static bool Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys);
|
||||
static bool Recover(CDBEnv& dbenv, const std::string& filename);
|
||||
|
||||
bool WriteHDSeed(const HDSeed& seed);
|
||||
bool WriteCryptedHDSeed(const uint256& seedFp, const std::vector<unsigned char>& vchCryptedSecret);
|
||||
//! write the hdchain model (external chain child index counter)
|
||||
bool WriteHDChain(const CHDChain& chain);
|
||||
|
||||
/// Write spending key to wallet database, where key is payment address and value is spending key.
|
||||
bool WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta);
|
||||
bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
|
||||
|
|
Loading…
Reference in New Issue