Browse Source

wallet: Store HDSeed and chain data

metaverse
Jack Grigg 6 years ago
parent
commit
e2416930ea
No known key found for this signature in database GPG Key ID: 1B8D649257DB0829
  1. 86
      src/wallet/wallet.cpp
  2. 28
      src/wallet/wallet.h
  3. 59
      src/wallet/walletdb.cpp
  4. 39
      src/wallet/walletdb.h

86
src/wallet/wallet.cpp

@ -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 &noteData)
{
mapSproutNoteData.clear();

28
src/wallet/wallet.h

@ -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.
@ -1222,6 +1229,27 @@ public:
bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
/** 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,

59
src/wallet/walletdb.cpp

@ -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);
}

39
src/wallet/walletdb.h

@ -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…
Cancel
Save