Persist Sapling key material in the wallet to disk
This commit is contained in:
parent
1b79de781c
commit
2fcf06077f
|
@ -23,6 +23,7 @@ testScripts=(
|
||||||
'wallet_mergetoaddress.py'
|
'wallet_mergetoaddress.py'
|
||||||
'wallet.py'
|
'wallet.py'
|
||||||
'wallet_overwintertx.py'
|
'wallet_overwintertx.py'
|
||||||
|
'wallet_persistence.py'
|
||||||
'wallet_nullifiers.py'
|
'wallet_nullifiers.py'
|
||||||
'wallet_1941.py'
|
'wallet_1941.py'
|
||||||
'wallet_addresses.py'
|
'wallet_addresses.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()
|
|
@ -166,7 +166,10 @@ bool CWallet::AddSaplingZKey(
|
||||||
return true;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -302,7 +305,16 @@ bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullVi
|
||||||
if (!fFileBacked)
|
if (!fFileBacked)
|
||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -334,6 +346,25 @@ bool CWallet::LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const
|
||||||
return CCryptoKeyStore::AddCryptedSproutSpendingKey(addr, rk, vchCryptedSecret);
|
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)
|
bool CWallet::LoadZKey(const libzcash::SproutSpendingKey &key)
|
||||||
{
|
{
|
||||||
return CCryptoKeyStore::AddSproutSpendingKey(key);
|
return CCryptoKeyStore::AddSproutSpendingKey(key);
|
||||||
|
|
|
@ -1063,6 +1063,13 @@ public:
|
||||||
const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||||
const std::vector<unsigned char> &vchCryptedSecret,
|
const std::vector<unsigned char> &vchCryptedSecret,
|
||||||
const libzcash::SaplingPaymentAddress &defaultAddr);
|
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
|
* Increment the next transaction order id
|
||||||
|
|
|
@ -125,6 +125,28 @@ bool CWalletDB::WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
|
||||||
return true;
|
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)
|
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
|
||||||
{
|
{
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdated++;
|
||||||
|
@ -141,6 +163,17 @@ bool CWalletDB::WriteZKey(const libzcash::SproutPaymentAddress& addr, const libz
|
||||||
// pair is: tuple_key("zkey", paymentaddress) --> secretkey
|
// pair is: tuple_key("zkey", paymentaddress) --> secretkey
|
||||||
return Write(std::make_pair(std::string("zkey"), addr), key, false);
|
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)
|
bool CWalletDB::WriteSproutViewingKey(const libzcash::SproutViewingKey &vk)
|
||||||
{
|
{
|
||||||
|
@ -511,6 +544,23 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||||
|
|
||||||
wss.nZKeys++;
|
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")
|
else if (strType == "key" || strType == "wkey")
|
||||||
{
|
{
|
||||||
CPubKey vchPubKey;
|
CPubKey vchPubKey;
|
||||||
|
@ -624,6 +674,23 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||||
}
|
}
|
||||||
wss.fIsEncrypted = true;
|
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")
|
else if (strType == "keymeta")
|
||||||
{
|
{
|
||||||
CPubKey vchPubKey;
|
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
|
// 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")
|
else if (strType == "defaultkey")
|
||||||
{
|
{
|
||||||
ssValue >> pwallet->vchDefaultKey;
|
ssValue >> pwallet->vchDefaultKey;
|
||||||
|
@ -736,7 +814,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||||
ssValue >> vchCryptedSecret;
|
ssValue >> vchCryptedSecret;
|
||||||
if (!pwallet->LoadCryptedHDSeed(seedFp, vchCryptedSecret))
|
if (!pwallet->LoadCryptedHDSeed(seedFp, vchCryptedSecret))
|
||||||
{
|
{
|
||||||
strErr = "Error reading wallet database: LoadCryptedSeed failed";
|
strErr = "Error reading wallet database: LoadCryptedHDSeed failed";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
wss.fIsEncrypted = true;
|
wss.fIsEncrypted = true;
|
||||||
|
@ -759,6 +837,7 @@ static bool IsKeyType(string strType)
|
||||||
return (strType== "key" || strType == "wkey" ||
|
return (strType== "key" || strType == "wkey" ||
|
||||||
strType == "hdseed" || strType == "chdseed" ||
|
strType == "hdseed" || strType == "chdseed" ||
|
||||||
strType == "zkey" || strType == "czkey" ||
|
strType == "zkey" || strType == "czkey" ||
|
||||||
|
strType == "sapzkey" || strType == "csapzkey" ||
|
||||||
strType == "vkey" ||
|
strType == "vkey" ||
|
||||||
strType == "mkey" || strType == "ckey");
|
strType == "mkey" || strType == "ckey");
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,10 +184,16 @@ public:
|
||||||
|
|
||||||
/// 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 WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk,
|
||||||
|
const libzcash::SaplingExtendedSpendingKey &key,
|
||||||
|
const CKeyMetadata &keyMeta);
|
||||||
bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
|
bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
|
||||||
const libzcash::ReceivingKey & rk,
|
const libzcash::ReceivingKey & rk,
|
||||||
const std::vector<unsigned char>& vchCryptedSecret,
|
const std::vector<unsigned char>& vchCryptedSecret,
|
||||||
const CKeyMetadata &keyMeta);
|
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 WriteSproutViewingKey(const libzcash::SproutViewingKey &vk);
|
||||||
bool EraseSproutViewingKey(const libzcash::SproutViewingKey &vk);
|
bool EraseSproutViewingKey(const libzcash::SproutViewingKey &vk);
|
||||||
|
|
Loading…
Reference in New Issue