wallet: Store HDSeed and chain data
This commit is contained in:
@@ -1865,6 +1865,92 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
|
|||||||
return nChange;
|
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)
|
void CWalletTx::SetSproutNoteData(mapSproutNoteData_t ¬eData)
|
||||||
{
|
{
|
||||||
mapSproutNoteData.clear();
|
mapSproutNoteData.clear();
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "wallet/walletdb.h"
|
#include "wallet/walletdb.h"
|
||||||
#include "wallet/rpcwallet.h"
|
#include "wallet/rpcwallet.h"
|
||||||
#include "zcash/Address.hpp"
|
#include "zcash/Address.hpp"
|
||||||
|
#include "zcash/zip32.h"
|
||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -61,6 +62,9 @@ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
|
|||||||
// unless there is some exceptional network disruption.
|
// unless there is some exceptional network disruption.
|
||||||
static const unsigned int WITNESS_CACHE_SIZE = MAX_REORG_LENGTH + 1;
|
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 CBlockIndex;
|
||||||
class CCoinControl;
|
class CCoinControl;
|
||||||
class COutput;
|
class COutput;
|
||||||
@@ -823,6 +827,9 @@ protected:
|
|||||||
bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx);
|
bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx);
|
||||||
void MarkAffectedTransactionsDirty(const CTransaction& tx);
|
void MarkAffectedTransactionsDirty(const CTransaction& tx);
|
||||||
|
|
||||||
|
/* the hd chain data model (chain counters) */
|
||||||
|
CHDChain hdChain;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
* Main wallet lock.
|
* Main wallet lock.
|
||||||
@@ -1222,6 +1229,27 @@ public:
|
|||||||
bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
|
bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
|
||||||
/** Set whether this wallet broadcasts transactions. */
|
/** Set whether this wallet broadcasts transactions. */
|
||||||
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
|
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 */
|
/* Find notes filtered by payment address, min depth, ability to spend */
|
||||||
void GetFilteredNotes(std::vector<CSproutNotePlaintextEntry>& sproutEntries,
|
void GetFilteredNotes(std::vector<CSproutNotePlaintextEntry>& sproutEntries,
|
||||||
|
|||||||
@@ -708,6 +708,45 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||||||
{
|
{
|
||||||
ssValue >> pwallet->nWitnessCacheSize;
|
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 (...)
|
} catch (...)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -718,6 +757,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||||||
static bool IsKeyType(string strType)
|
static bool IsKeyType(string strType)
|
||||||
{
|
{
|
||||||
return (strType== "key" || strType == "wkey" ||
|
return (strType== "key" || strType == "wkey" ||
|
||||||
|
strType == "hdseed" || strType == "chdseed" ||
|
||||||
strType == "zkey" || strType == "czkey" ||
|
strType == "zkey" || strType == "czkey" ||
|
||||||
strType == "vkey" ||
|
strType == "vkey" ||
|
||||||
strType == "mkey" || strType == "ckey");
|
strType == "mkey" || strType == "ckey");
|
||||||
@@ -1103,3 +1143,22 @@ bool CWalletDB::EraseDestData(const std::string &address, const std::string &key
|
|||||||
nWalletDBUpdated++;
|
nWalletDBUpdated++;
|
||||||
return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
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 "key.h"
|
||||||
#include "keystore.h"
|
#include "keystore.h"
|
||||||
#include "zcash/Address.hpp"
|
#include "zcash/Address.hpp"
|
||||||
|
#include "zcash/zip32.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -40,6 +41,39 @@ enum DBErrors
|
|||||||
DB_NEED_REWRITE
|
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
|
class CKeyMetadata
|
||||||
{
|
{
|
||||||
public:
|
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 fOnlyKeys);
|
||||||
static bool Recover(CDBEnv& dbenv, const std::string& filename);
|
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.
|
/// 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 WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta);
|
||||||
bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
|
bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
|
||||||
|
|||||||
Reference in New Issue
Block a user