wallet: Switch from SaplingSpendingKey to SaplingExtendedSpendingKey
The wallet now only stores Sapling extended spending keys, and thus can only be used with keys generated from an HDSeed via ZIP 32. Note that not all Sapling keys in the wallet will correspond to the wallet's HDSeed, as a standalone Sapling xsk can be imported via z_importkey. However, it must have been generated from a seed itself, and thus is more likely to be backed up elsewhere.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "utilmoneystr.h"
|
||||
#include "zcash/Note.hpp"
|
||||
#include "crypter.h"
|
||||
#include "zcash/zip32.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -104,22 +105,42 @@ libzcash::PaymentAddress CWallet::GenerateNewZKey()
|
||||
SaplingPaymentAddress CWallet::GenerateNewSaplingZKey()
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
||||
|
||||
auto sk = SaplingSpendingKey::random();
|
||||
auto fvk = sk.full_viewing_key();
|
||||
auto ivk = fvk.in_viewing_key();
|
||||
auto addr = sk.default_address();
|
||||
|
||||
// Check for collision, even though it is unlikely to ever occur
|
||||
if (CCryptoKeyStore::HaveSaplingSpendingKey(fvk)) {
|
||||
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): Collision detected");
|
||||
}
|
||||
|
||||
|
||||
// Create new metadata
|
||||
int64_t nCreationTime = GetTime();
|
||||
mapSaplingZKeyMetadata[ivk] = CKeyMetadata(nCreationTime);
|
||||
CKeyMetadata metadata(nCreationTime);
|
||||
|
||||
if (!AddSaplingZKey(sk, addr)) {
|
||||
// Try to get the seed
|
||||
HDSeed seed;
|
||||
if (!GetHDSeed(seed))
|
||||
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): HD seed not found");
|
||||
|
||||
auto m = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
|
||||
// We use a fixed keypath scheme of m/32'/coin_type'/account'
|
||||
// Derive m/32'
|
||||
auto m_32h = m.Derive(32 | ZIP32_HARDENED_KEY_LIMIT);
|
||||
// Derive m/32'/coin_type'
|
||||
auto m_32h_cth = m_32h.Derive(Params().BIP44CoinType() | ZIP32_HARDENED_KEY_LIMIT);
|
||||
|
||||
// Derive account key at next index, skip keys already known to the wallet
|
||||
libzcash::SaplingExtendedSpendingKey xsk;
|
||||
do
|
||||
{
|
||||
xsk = m_32h_cth.Derive(hdChain.saplingAccountCounter | ZIP32_HARDENED_KEY_LIMIT);
|
||||
// Increment childkey index
|
||||
hdChain.saplingAccountCounter++;
|
||||
} while (HaveSaplingSpendingKey(xsk.expsk.full_viewing_key()));
|
||||
|
||||
// Update the chain model in the database
|
||||
if (fFileBacked && !CWalletDB(strWalletFile).WriteHDChain(hdChain))
|
||||
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): Writing HD chain model failed");
|
||||
|
||||
auto ivk = xsk.expsk.full_viewing_key().in_viewing_key();
|
||||
mapSaplingZKeyMetadata[ivk] = metadata;
|
||||
|
||||
auto addr = xsk.DefaultAddress();
|
||||
if (!AddSaplingZKey(xsk, addr)) {
|
||||
throw std::runtime_error("CWallet::GenerateNewSaplingZKey(): AddSaplingZKey failed");
|
||||
}
|
||||
// return default sapling payment address.
|
||||
@@ -128,7 +149,7 @@ SaplingPaymentAddress CWallet::GenerateNewSaplingZKey()
|
||||
|
||||
// Add spending key to keystore
|
||||
bool CWallet::AddSaplingZKey(
|
||||
const libzcash::SaplingSpendingKey &sk,
|
||||
const libzcash::SaplingExtendedSpendingKey &sk,
|
||||
const boost::optional<libzcash::SaplingPaymentAddress> &defaultAddr)
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
|
||||
@@ -4450,8 +4471,8 @@ bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAdd
|
||||
{
|
||||
libzcash::SaplingIncomingViewingKey ivk;
|
||||
|
||||
// If we have a SaplingSpendingKey or SaplingExpandedSpendingKey in the
|
||||
// wallet, then we will also have the corresponding SaplingFullViewingKey.
|
||||
// If we have a SaplingExtendedSpendingKey in the wallet, then we will
|
||||
// also have the corresponding SaplingFullViewingKey.
|
||||
return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
|
||||
m_wallet->HaveSaplingFullViewingKey(ivk);
|
||||
}
|
||||
@@ -4497,7 +4518,7 @@ boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator
|
||||
{
|
||||
libzcash::SaplingIncomingViewingKey ivk;
|
||||
libzcash::SaplingFullViewingKey fvk;
|
||||
libzcash::SaplingSpendingKey sk;
|
||||
libzcash::SaplingExtendedSpendingKey sk;
|
||||
|
||||
if (m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
|
||||
m_wallet->GetSaplingFullViewingKey(ivk, fvk) &&
|
||||
|
||||
Reference in New Issue
Block a user