Browse Source

Persist Sapling key material in the wallet to disk

pull/4/head
mdr0id 6 years ago
committed by Jack Grigg
parent
commit
2fcf06077f
No known key found for this signature in database GPG Key ID: 1B8D649257DB0829
  1. 1
      qa/pull-tester/rpc-tests.sh
  2. 31
      qa/rpc-tests/wallet_persistence.py
  3. 35
      src/wallet/wallet.cpp
  4. 7
      src/wallet/wallet.h
  5. 81
      src/wallet/walletdb.cpp
  6. 6
      src/wallet/walletdb.h

1
qa/pull-tester/rpc-tests.sh

@ -23,6 +23,7 @@ testScripts=(
'wallet_mergetoaddress.py'
'wallet.py'
'wallet_overwintertx.py'
'wallet_persistence.py'
'wallet_nullifiers.py'
'wallet_1941.py'
'wallet_addresses.py'

31
qa/rpc-tests/wallet_persistence.py

@ -0,0 +1,31 @@
#!/usr/bin/env python2
# Copyright (c) 2018 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_true, start_nodes, stop_nodes, \
wait_bitcoinds
class WalletPersistenceTest (BitcoinTestFramework):
def setup_network(self, split=False):
self.nodes = start_nodes(1, self.options.tmpdir)
self.is_network_split = False
self.sync_all()
def run_test(self):
sapling_addr = self.nodes[0].z_getnewaddress('sapling')
addresses = self.nodes[0].z_listaddresses()
# make sure the node has the addresss
assert_true(sapling_addr in addresses, "Should contain address before restart")
# restart the nodes
stop_nodes(self.nodes)
wait_bitcoinds()
self.nodes = self.setup_nodes()
addresses = self.nodes[0].z_listaddresses()
# make sure we still have the address after restarting
assert_true(sapling_addr in addresses, "Should contain address after restart")
if __name__ == '__main__':
WalletPersistenceTest().main()

35
src/wallet/wallet.cpp

@ -166,7 +166,10 @@ bool CWallet::AddSaplingZKey(
return true;
}
// TODO: Persist to disk
if (!IsCrypted()) {
auto ivk = sk.expsk.full_viewing_key().in_viewing_key();
return CWalletDB(strWalletFile).WriteSaplingZKey(ivk, sk, mapSaplingZKeyMetadata[ivk]);
}
return true;
}
@ -302,7 +305,16 @@ bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullVi
if (!fFileBacked)
return true;
{
// TODO: Sapling - Write to disk
LOCK(cs_wallet);
if (pwalletdbEncryption) {
return pwalletdbEncryption->WriteCryptedSaplingZKey(extfvk,
vchCryptedSecret,
mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
} else {
return CWalletDB(strWalletFile).WriteCryptedSaplingZKey(extfvk,
vchCryptedSecret,
mapSaplingZKeyMetadata[extfvk.fvk.in_viewing_key()]);
}
}
return false;
}
@ -334,6 +346,25 @@ bool CWallet::LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const
return CCryptoKeyStore::AddCryptedSproutSpendingKey(addr, rk, vchCryptedSecret);
}
bool CWallet::LoadCryptedSaplingZKey(
const libzcash::SaplingExtendedFullViewingKey &extfvk,
const std::vector<unsigned char> &vchCryptedSecret)
{
return CCryptoKeyStore::AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret, extfvk.DefaultAddress());
}
bool CWallet::LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta)
{
AssertLockHeld(cs_wallet); // mapSaplingZKeyMetadata
mapSaplingZKeyMetadata[ivk] = meta;
return true;
}
bool CWallet::LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
{
return CCryptoKeyStore::AddSaplingSpendingKey(key, key.DefaultAddress());
}
bool CWallet::LoadZKey(const libzcash::SproutSpendingKey &key)
{
return CCryptoKeyStore::AddSproutSpendingKey(key);

7
src/wallet/wallet.h

@ -1063,6 +1063,13 @@ public:
const libzcash::SaplingExtendedFullViewingKey &extfvk,
const std::vector<unsigned char> &vchCryptedSecret,
const libzcash::SaplingPaymentAddress &defaultAddr);
//! Adds spending key to the store, without saving it to disk (used by LoadWallet)
bool LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key);
//! Load spending key metadata (used by LoadWallet)
bool LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta);
//! Adds an encrypted spending key to the store, without saving it to disk (used by LoadWallet)
bool LoadCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
const std::vector<unsigned char> &vchCryptedSecret);
/**
* Increment the next transaction order id

81
src/wallet/walletdb.cpp

@ -125,6 +125,28 @@ bool CWalletDB::WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
return true;
}
bool CWalletDB::WriteCryptedSaplingZKey(
const libzcash::SaplingExtendedFullViewingKey &extfvk,
const std::vector<unsigned char>& vchCryptedSecret,
const CKeyMetadata &keyMeta)
{
const bool fEraseUnencryptedKey = true;
nWalletDBUpdated++;
auto ivk = extfvk.fvk.in_viewing_key();
if (!Write(std::make_pair(std::string("sapzkeymeta"), ivk), keyMeta))
return false;
if (!Write(std::make_pair(std::string("csapzkey"), ivk), std::make_pair(extfvk, vchCryptedSecret), false))
return false;
if (fEraseUnencryptedKey)
{
Erase(std::make_pair(std::string("sapzkey"), ivk));
}
return true;
}
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
{
nWalletDBUpdated++;
@ -141,6 +163,17 @@ bool CWalletDB::WriteZKey(const libzcash::SproutPaymentAddress& addr, const libz
// pair is: tuple_key("zkey", paymentaddress) --> secretkey
return Write(std::make_pair(std::string("zkey"), addr), key, false);
}
bool CWalletDB::WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk,
const libzcash::SaplingExtendedSpendingKey &key,
const CKeyMetadata &keyMeta)
{
nWalletDBUpdated++;
if (!Write(std::make_pair(std::string("sapzkeymeta"), ivk), keyMeta))
return false;
return Write(std::make_pair(std::string("sapzkey"), ivk), key, false);
}
bool CWalletDB::WriteSproutViewingKey(const libzcash::SproutViewingKey &vk)
{
@ -511,6 +544,23 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
wss.nZKeys++;
}
else if (strType == "sapzkey")
{
libzcash::SaplingIncomingViewingKey ivk;
ssKey >> ivk;
libzcash::SaplingExtendedSpendingKey key;
ssValue >> key;
if (!pwallet->LoadSaplingZKey(key))
{
strErr = "Error reading wallet database: LoadSaplingZKey failed";
return false;
}
//add checks for integrity
wss.nZKeys++;
}
else if (strType == "key" || strType == "wkey")
{
CPubKey vchPubKey;
@ -624,6 +674,23 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
}
wss.fIsEncrypted = true;
}
else if (strType == "csapzkey")
{
libzcash::SaplingIncomingViewingKey ivk;
ssKey >> ivk;
libzcash::SaplingExtendedFullViewingKey extfvk;
ssValue >> extfvk;
vector<unsigned char> vchCryptedSecret;
ssValue >> vchCryptedSecret;
wss.nCKeys++;
if (!pwallet->LoadCryptedSaplingZKey(extfvk, vchCryptedSecret))
{
strErr = "Error reading wallet database: LoadCryptedSaplingZKey failed";
return false;
}
wss.fIsEncrypted = true;
}
else if (strType == "keymeta")
{
CPubKey vchPubKey;
@ -651,6 +718,17 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
// ignore earliest key creation time as taddr will exist before any zaddr
}
else if (strType == "sapzkeymeta")
{
libzcash::SaplingIncomingViewingKey ivk;
ssKey >> ivk;
CKeyMetadata keyMeta;
ssValue >> keyMeta;
wss.nZKeyMeta++;
pwallet->LoadSaplingZKeyMetadata(ivk, keyMeta);
}
else if (strType == "defaultkey")
{
ssValue >> pwallet->vchDefaultKey;
@ -736,7 +814,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssValue >> vchCryptedSecret;
if (!pwallet->LoadCryptedHDSeed(seedFp, vchCryptedSecret))
{
strErr = "Error reading wallet database: LoadCryptedSeed failed";
strErr = "Error reading wallet database: LoadCryptedHDSeed failed";
return false;
}
wss.fIsEncrypted = true;
@ -759,6 +837,7 @@ static bool IsKeyType(string strType)
return (strType== "key" || strType == "wkey" ||
strType == "hdseed" || strType == "chdseed" ||
strType == "zkey" || strType == "czkey" ||
strType == "sapzkey" || strType == "csapzkey" ||
strType == "vkey" ||
strType == "mkey" || strType == "ckey");
}

6
src/wallet/walletdb.h

@ -184,10 +184,16 @@ public:
/// 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 WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk,
const libzcash::SaplingExtendedSpendingKey &key,
const CKeyMetadata &keyMeta);
bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
const libzcash::ReceivingKey & rk,
const std::vector<unsigned char>& vchCryptedSecret,
const CKeyMetadata &keyMeta);
bool WriteCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
const std::vector<unsigned char>& vchCryptedSecret,
const CKeyMetadata &keyMeta);
bool WriteSproutViewingKey(const libzcash::SproutViewingKey &vk);
bool EraseSproutViewingKey(const libzcash::SproutViewingKey &vk);

Loading…
Cancel
Save