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:
@@ -382,8 +382,8 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
SaplingExpandedSpendingKey expsk;
|
||||
SaplingFullViewingKey from;
|
||||
if (isfromzaddr_) {
|
||||
auto sk = boost::get<libzcash::SaplingSpendingKey>(spendingkey_);
|
||||
expsk = sk.expanded_spending_key();
|
||||
auto sk = boost::get<libzcash::SaplingExtendedSpendingKey>(spendingkey_);
|
||||
expsk = sk.expsk;
|
||||
from = expsk.full_viewing_key();
|
||||
} else {
|
||||
// TODO: Set "from" to something!
|
||||
|
||||
@@ -171,18 +171,18 @@ static bool DecryptSproutSpendingKey(const CKeyingMaterial& vMasterKey,
|
||||
static bool DecryptSaplingSpendingKey(const CKeyingMaterial& vMasterKey,
|
||||
const std::vector<unsigned char>& vchCryptedSecret,
|
||||
const libzcash::SaplingFullViewingKey& fvk,
|
||||
libzcash::SaplingSpendingKey& sk)
|
||||
libzcash::SaplingExtendedSpendingKey& sk)
|
||||
{
|
||||
CKeyingMaterial vchSecret;
|
||||
if (!DecryptSecret(vMasterKey, vchCryptedSecret, fvk.GetFingerprint(), vchSecret))
|
||||
return false;
|
||||
|
||||
if (vchSecret.size() != libzcash::SerializedSaplingSpendingKeySize)
|
||||
if (vchSecret.size() != ZIP32_XSK_SIZE)
|
||||
return false;
|
||||
|
||||
CSecureDataStream ss(vchSecret, SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> sk;
|
||||
return sk.full_viewing_key() == fvk;
|
||||
return sk.expsk.full_viewing_key() == fvk;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::SetCrypted()
|
||||
@@ -263,7 +263,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
const libzcash::SaplingFullViewingKey &fvk = (*miSapling).first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*miSapling).second;
|
||||
libzcash::SaplingSpendingKey sk;
|
||||
libzcash::SaplingExtendedSpendingKey sk;
|
||||
if (!DecryptSaplingSpendingKey(vMasterKeyIn, vchCryptedSecret, fvk, sk))
|
||||
{
|
||||
keyFail = true;
|
||||
@@ -442,7 +442,7 @@ bool CCryptoKeyStore::AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::AddSaplingSpendingKey(
|
||||
const libzcash::SaplingSpendingKey &sk,
|
||||
const libzcash::SaplingExtendedSpendingKey &sk,
|
||||
const boost::optional<libzcash::SaplingPaymentAddress> &defaultAddr)
|
||||
{
|
||||
{
|
||||
@@ -459,7 +459,7 @@ bool CCryptoKeyStore::AddSaplingSpendingKey(
|
||||
CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << sk;
|
||||
CKeyingMaterial vchSecret(ss.begin(), ss.end());
|
||||
auto fvk = sk.full_viewing_key();
|
||||
auto fvk = sk.expsk.full_viewing_key();
|
||||
if (!EncryptSecret(vMasterKey, vchSecret, fvk.GetFingerprint(), vchCryptedSecret)) {
|
||||
return false;
|
||||
}
|
||||
@@ -525,7 +525,7 @@ bool CCryptoKeyStore::GetSproutSpendingKey(const libzcash::SproutPaymentAddress
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk, libzcash::SaplingSpendingKey &skOut) const
|
||||
bool CCryptoKeyStore::GetSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk, libzcash::SaplingExtendedSpendingKey &skOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_SpendingKeyStore);
|
||||
@@ -597,11 +597,11 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
//! Sapling key support
|
||||
BOOST_FOREACH(SaplingSpendingKeyMap::value_type& mSaplingSpendingKey, mapSaplingSpendingKeys)
|
||||
{
|
||||
const libzcash::SaplingSpendingKey &sk = mSaplingSpendingKey.second;
|
||||
const auto &sk = mSaplingSpendingKey.second;
|
||||
CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << sk;
|
||||
CKeyingMaterial vchSecret(ss.begin(), ss.end());
|
||||
libzcash::SaplingFullViewingKey fvk = sk.full_viewing_key();
|
||||
libzcash::SaplingFullViewingKey fvk = sk.expsk.full_viewing_key();
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
if (!EncryptSecret(vMasterKeyIn, vchSecret, fvk.GetFingerprint(), vchCryptedSecret)) {
|
||||
return false;
|
||||
|
||||
@@ -245,7 +245,7 @@ public:
|
||||
const std::vector<unsigned char> &vchCryptedSecret,
|
||||
const boost::optional<libzcash::SaplingPaymentAddress> &defaultAddr = boost::none);
|
||||
bool AddSaplingSpendingKey(
|
||||
const libzcash::SaplingSpendingKey &sk,
|
||||
const libzcash::SaplingExtendedSpendingKey &sk,
|
||||
const boost::optional<libzcash::SaplingPaymentAddress> &defaultAddr = boost::none);
|
||||
bool HaveSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk) const
|
||||
{
|
||||
@@ -257,7 +257,7 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool GetSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk, libzcash::SaplingSpendingKey &skOut) const;
|
||||
bool GetSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk, libzcash::SaplingExtendedSpendingKey &skOut) const;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -363,11 +363,13 @@ TEST(WalletTests, SetSaplingNoteAddrsInCWalletTx) {
|
||||
|
||||
TestWallet wallet;
|
||||
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
auto expsk = sk.expanded_spending_key();
|
||||
auto fvk = sk.full_viewing_key();
|
||||
auto pk = sk.default_address();
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
|
||||
HDSeed seed(rawSeed);
|
||||
auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
auto expsk = sk.expsk;
|
||||
auto fvk = expsk.full_viewing_key();
|
||||
auto ivk = fvk.in_viewing_key();
|
||||
auto pk = sk.DefaultAddress();
|
||||
|
||||
libzcash::SaplingNote note(pk, 50000);
|
||||
auto cm = note.cm().get();
|
||||
@@ -484,10 +486,12 @@ TEST(WalletTests, FindMySaplingNotes) {
|
||||
TestWallet wallet;
|
||||
|
||||
// Generate dummy Sapling address
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
auto expsk = sk.expanded_spending_key();
|
||||
auto fvk = sk.full_viewing_key();
|
||||
auto pk = sk.default_address();
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
|
||||
HDSeed seed(rawSeed);
|
||||
auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
auto expsk = sk.expsk;
|
||||
auto fvk = expsk.full_viewing_key();
|
||||
auto pk = sk.DefaultAddress();
|
||||
|
||||
// Generate dummy Sapling note
|
||||
libzcash::SaplingNote note(pk, 50000);
|
||||
@@ -618,11 +622,13 @@ TEST(WalletTests, GetConflictedSaplingNotes) {
|
||||
TestWallet wallet;
|
||||
|
||||
// Generate Sapling address
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
auto expsk = sk.expanded_spending_key();
|
||||
auto fvk = sk.full_viewing_key();
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
|
||||
HDSeed seed(rawSeed);
|
||||
auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
auto expsk = sk.expsk;
|
||||
auto fvk = expsk.full_viewing_key();
|
||||
auto ivk = fvk.in_viewing_key();
|
||||
auto pk = sk.default_address();
|
||||
auto pk = sk.DefaultAddress();
|
||||
|
||||
ASSERT_TRUE(wallet.AddSaplingZKey(sk));
|
||||
ASSERT_TRUE(wallet.HaveSaplingSpendingKey(fvk));
|
||||
@@ -785,10 +791,12 @@ TEST(WalletTests, SaplingNullifierIsSpent) {
|
||||
TestWallet wallet;
|
||||
|
||||
// Generate dummy Sapling address
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
auto expsk = sk.expanded_spending_key();
|
||||
auto fvk = sk.full_viewing_key();
|
||||
auto pk = sk.default_address();
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
|
||||
HDSeed seed(rawSeed);
|
||||
auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
auto expsk = sk.expsk;
|
||||
auto fvk = expsk.full_viewing_key();
|
||||
auto pk = sk.DefaultAddress();
|
||||
|
||||
// Generate dummy Sapling note
|
||||
libzcash::SaplingNote note(pk, 50000);
|
||||
@@ -880,10 +888,12 @@ TEST(WalletTests, NavigateFromSaplingNullifierToNote) {
|
||||
TestWallet wallet;
|
||||
|
||||
// Generate dummy Sapling address
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
auto expsk = sk.expanded_spending_key();
|
||||
auto fvk = sk.full_viewing_key();
|
||||
auto pk = sk.default_address();
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
|
||||
HDSeed seed(rawSeed);
|
||||
auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
auto expsk = sk.expsk;
|
||||
auto fvk = expsk.full_viewing_key();
|
||||
auto pk = sk.DefaultAddress();
|
||||
|
||||
// Generate dummy Sapling note
|
||||
libzcash::SaplingNote note(pk, 50000);
|
||||
@@ -1013,11 +1023,13 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) {
|
||||
TestWallet wallet;
|
||||
|
||||
// Generate Sapling address
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
auto expsk = sk.expanded_spending_key();
|
||||
auto fvk = sk.full_viewing_key();
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
|
||||
HDSeed seed(rawSeed);
|
||||
auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
auto expsk = sk.expsk;
|
||||
auto fvk = expsk.full_viewing_key();
|
||||
auto ivk = fvk.in_viewing_key();
|
||||
auto pk = sk.default_address();
|
||||
auto pk = sk.DefaultAddress();
|
||||
|
||||
// Generate Sapling note A
|
||||
libzcash::SaplingNote note(pk, 50000);
|
||||
@@ -1705,16 +1717,21 @@ TEST(WalletTests, UpdatedSaplingNoteData) {
|
||||
|
||||
TestWallet wallet;
|
||||
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
|
||||
HDSeed seed(rawSeed);
|
||||
auto m = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
|
||||
// Generate dummy Sapling address
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
auto expsk = sk.expanded_spending_key();
|
||||
auto fvk = sk.full_viewing_key();
|
||||
auto pk = sk.default_address();
|
||||
auto sk = m.Derive(0);
|
||||
auto expsk = sk.expsk;
|
||||
auto fvk = expsk.full_viewing_key();
|
||||
auto pk = sk.DefaultAddress();
|
||||
|
||||
// Generate dummy recipient Sapling address
|
||||
auto sk2 = libzcash::SaplingSpendingKey::random();
|
||||
auto fvk2 = sk2.full_viewing_key();
|
||||
auto pk2 = sk2.default_address();
|
||||
auto sk2 = m.Derive(1);
|
||||
auto expsk2 = sk2.expsk;
|
||||
auto fvk2 = expsk2.full_viewing_key();
|
||||
auto pk2 = sk2.DefaultAddress();
|
||||
|
||||
// Generate dummy Sapling note
|
||||
libzcash::SaplingNote note(pk, 50000);
|
||||
@@ -1856,11 +1873,13 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) {
|
||||
TestWallet wallet;
|
||||
|
||||
// Generate Sapling address
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
auto expsk = sk.expanded_spending_key();
|
||||
auto fvk = sk.full_viewing_key();
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
|
||||
HDSeed seed(rawSeed);
|
||||
auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
auto expsk = sk.expsk;
|
||||
auto fvk = expsk.full_viewing_key();
|
||||
auto ivk = fvk.in_viewing_key();
|
||||
auto pk = sk.default_address();
|
||||
auto pk = sk.DefaultAddress();
|
||||
|
||||
ASSERT_TRUE(wallet.AddSaplingZKey(sk));
|
||||
ASSERT_TRUE(wallet.HaveSaplingSpendingKey(fvk));
|
||||
|
||||
@@ -21,8 +21,18 @@ TEST(wallet_zkeys_tests, store_and_load_sapling_zkeys) {
|
||||
wallet.GetSaplingPaymentAddresses(addrs);
|
||||
ASSERT_EQ(0, addrs.size());
|
||||
|
||||
// wallet should have one key
|
||||
// No HD seed in the wallet
|
||||
EXPECT_ANY_THROW(wallet.GenerateNewSaplingZKey());
|
||||
|
||||
// Load the all-zeroes seed
|
||||
CKeyingMaterial rawSeed(32, 0);
|
||||
HDSeed seed(rawSeed);
|
||||
wallet.LoadHDSeed(seed);
|
||||
|
||||
// Now this call succeeds
|
||||
auto address = wallet.GenerateNewSaplingZKey();
|
||||
|
||||
// wallet should have one key
|
||||
wallet.GetSaplingPaymentAddresses(addrs);
|
||||
ASSERT_EQ(1, addrs.size());
|
||||
|
||||
@@ -30,15 +40,16 @@ TEST(wallet_zkeys_tests, store_and_load_sapling_zkeys) {
|
||||
ASSERT_TRUE(wallet.HaveSaplingIncomingViewingKey(address));
|
||||
|
||||
// manually add new spending key to wallet
|
||||
auto sk = libzcash::SaplingSpendingKey::random();
|
||||
ASSERT_TRUE(wallet.AddSaplingZKey(sk, sk.default_address()));
|
||||
auto m = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
auto sk = m.Derive(0);
|
||||
ASSERT_TRUE(wallet.AddSaplingZKey(sk, sk.DefaultAddress()));
|
||||
|
||||
// verify wallet did add it
|
||||
auto fvk = sk.full_viewing_key();
|
||||
auto fvk = sk.expsk.full_viewing_key();
|
||||
ASSERT_TRUE(wallet.HaveSaplingSpendingKey(fvk));
|
||||
|
||||
// verify spending key stored correctly
|
||||
libzcash::SaplingSpendingKey keyOut;
|
||||
libzcash::SaplingExtendedSpendingKey keyOut;
|
||||
wallet.GetSaplingSpendingKey(fvk, keyOut);
|
||||
ASSERT_EQ(sk, keyOut);
|
||||
|
||||
@@ -46,7 +57,7 @@ TEST(wallet_zkeys_tests, store_and_load_sapling_zkeys) {
|
||||
wallet.GetSaplingPaymentAddresses(addrs);
|
||||
EXPECT_EQ(2, addrs.size());
|
||||
EXPECT_EQ(1, addrs.count(address));
|
||||
EXPECT_EQ(1, addrs.count(sk.default_address()));
|
||||
EXPECT_EQ(1, addrs.count(sk.DefaultAddress()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -576,18 +576,18 @@ public:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator()(const libzcash::SaplingSpendingKey &sk) const {
|
||||
auto fvk = sk.full_viewing_key();
|
||||
|
||||
bool operator()(const libzcash::SaplingExtendedSpendingKey &sk) const {
|
||||
auto fvk = sk.expsk.full_viewing_key();
|
||||
auto ivk = fvk.in_viewing_key();
|
||||
auto addr = sk.default_address();
|
||||
auto addr = sk.DefaultAddress();
|
||||
{
|
||||
// Don't throw error in case a key is already there
|
||||
if (m_wallet->HaveSaplingSpendingKey(fvk)) {
|
||||
return true;
|
||||
} else {
|
||||
m_wallet->MarkDirty();
|
||||
|
||||
|
||||
if (!m_wallet-> AddSaplingZKey(sk, addr)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding spending key to wallet");
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "primitives/transaction.h"
|
||||
#include "zcbenchmarks.h"
|
||||
#include "script/interpreter.h"
|
||||
#include "zcash/zip32.h"
|
||||
|
||||
#include "utiltime.h"
|
||||
#include "asyncrpcoperation.h"
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
@@ -1052,7 +1052,7 @@ public:
|
||||
libzcash::SaplingPaymentAddress GenerateNewSaplingZKey();
|
||||
//! Adds Sapling spending key to the store, and saves it to disk
|
||||
bool AddSaplingZKey(
|
||||
const libzcash::SaplingSpendingKey &key,
|
||||
const libzcash::SaplingExtendedSpendingKey &key,
|
||||
const boost::optional<libzcash::SaplingPaymentAddress> &defaultAddr = boost::none);
|
||||
bool AddCryptedSaplingSpendingKey(
|
||||
const libzcash::SaplingFullViewingKey &fvk,
|
||||
|
||||
Reference in New Issue
Block a user