Export zip32 metadata with sapling keys
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_true, start_nodes
|
from test_framework.util import assert_equal, assert_true, start_nodes
|
||||||
|
|
||||||
class WalletImportExportTest (BitcoinTestFramework):
|
class WalletImportExportTest (BitcoinTestFramework):
|
||||||
def setup_network(self, split=False):
|
def setup_network(self, split=False):
|
||||||
@@ -19,6 +19,9 @@ class WalletImportExportTest (BitcoinTestFramework):
|
|||||||
dump_path0 = self.nodes[0].z_exportwallet('walletdump')
|
dump_path0 = self.nodes[0].z_exportwallet('walletdump')
|
||||||
(t_keys0, sprout_keys0, sapling_keys0) = parse_wallet_file(dump_path0)
|
(t_keys0, sprout_keys0, sapling_keys0) = parse_wallet_file(dump_path0)
|
||||||
|
|
||||||
|
for sapling_key0 in sapling_keys0.splitlines():
|
||||||
|
assert_equal(4, len(sapling_key0.split(' #')[0].split()), "Should have 4 parameters before ' #'")
|
||||||
|
|
||||||
assert_true(sprout_address0 in sprout_keys0)
|
assert_true(sprout_address0 in sprout_keys0)
|
||||||
assert_true(sapling_address0 in sapling_keys0)
|
assert_true(sapling_address0 in sapling_keys0)
|
||||||
|
|
||||||
@@ -39,6 +42,10 @@ class WalletImportExportTest (BitcoinTestFramework):
|
|||||||
assert_true(sprout_address0 in sprout_keys1)
|
assert_true(sprout_address0 in sprout_keys1)
|
||||||
assert_true(sapling_address0 in sapling_keys1)
|
assert_true(sapling_address0 in sapling_keys1)
|
||||||
|
|
||||||
|
# make sure we have perserved the metadata
|
||||||
|
for sapling_key0 in sapling_keys0.splitlines():
|
||||||
|
assert_true(sapling_key0 in sapling_keys1)
|
||||||
|
|
||||||
# Helper functions
|
# Helper functions
|
||||||
def parse_wallet_file(dump_path):
|
def parse_wallet_file(dump_path):
|
||||||
file_lines = open(dump_path, "r").readlines()
|
file_lines = open(dump_path, "r").readlines()
|
||||||
@@ -60,7 +67,7 @@ def parse_wallet_file_lines(file_lines, i):
|
|||||||
while i < len(file_lines) and not (file_lines[i] == '\n' or file_lines[i].startswith("#")):
|
while i < len(file_lines) and not (file_lines[i] == '\n' or file_lines[i].startswith("#")):
|
||||||
keys.append(file_lines[i])
|
keys.append(file_lines[i])
|
||||||
i += 1
|
i += 1
|
||||||
return ("".join(keys), i)
|
return ("\n".join(keys), i)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
WalletImportExportTest().main()
|
WalletImportExportTest().main()
|
||||||
@@ -298,9 +298,11 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys
|
|||||||
if (fImportZKeys) {
|
if (fImportZKeys) {
|
||||||
auto spendingkey = DecodeSpendingKey(vstr[0]);
|
auto spendingkey = DecodeSpendingKey(vstr[0]);
|
||||||
int64_t nTime = DecodeDumpTime(vstr[1]);
|
int64_t nTime = DecodeDumpTime(vstr[1]);
|
||||||
|
boost::optional<std::string> hdKeypath = (vstr.size() > 2) ? boost::optional<std::string>(vstr[2]) : boost::none;
|
||||||
|
boost::optional<std::string> seedFpStr = (vstr.size() > 3) ? boost::optional<std::string>(vstr[3]) : boost::none;
|
||||||
if (IsValidSpendingKey(spendingkey)) {
|
if (IsValidSpendingKey(spendingkey)) {
|
||||||
auto addResult = boost::apply_visitor(
|
auto addResult = boost::apply_visitor(
|
||||||
AddSpendingKeyToWallet(pwalletMain, Params().GetConsensus(), nTime, true), spendingkey);
|
AddSpendingKeyToWallet(pwalletMain, Params().GetConsensus(), nTime, hdKeypath, seedFpStr, true), spendingkey);
|
||||||
if (addResult == KeyAlreadyExists){
|
if (addResult == KeyAlreadyExists){
|
||||||
LogPrint("zrpc", "Skipping import of zaddr (key already present)\n");
|
LogPrint("zrpc", "Skipping import of zaddr (key already present)\n");
|
||||||
} else if (addResult == KeyNotAdded) {
|
} else if (addResult == KeyNotAdded) {
|
||||||
@@ -548,8 +550,9 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
|
|||||||
libzcash::SaplingExtendedSpendingKey extsk;
|
libzcash::SaplingExtendedSpendingKey extsk;
|
||||||
if (pwalletMain->GetSaplingExtendedSpendingKey(addr, extsk)) {
|
if (pwalletMain->GetSaplingExtendedSpendingKey(addr, extsk)) {
|
||||||
auto ivk = extsk.expsk.full_viewing_key().in_viewing_key();
|
auto ivk = extsk.expsk.full_viewing_key().in_viewing_key();
|
||||||
std::string strTime = EncodeDumpTime(pwalletMain->mapSaplingZKeyMetadata[ivk].nCreateTime);
|
CKeyMetadata keyMeta = pwalletMain->mapSaplingZKeyMetadata[ivk];
|
||||||
file << strprintf("%s %s # zaddr=%s\n", EncodeSpendingKey(extsk), strTime, EncodePaymentAddress(addr));
|
std::string strTime = EncodeDumpTime(keyMeta.nCreateTime);
|
||||||
|
file << strprintf("%s %s %s %s # zaddr=%s\n", EncodeSpendingKey(extsk), strTime, keyMeta.hdKeypath, keyMeta.seedFp.GetHex(), EncodePaymentAddress(addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file << "\n";
|
file << "\n";
|
||||||
@@ -633,8 +636,7 @@ UniValue z_importkey(const UniValue& params, bool fHelp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sapling support
|
// Sapling support
|
||||||
auto addResult = boost::apply_visitor(
|
auto addResult = boost::apply_visitor(AddSpendingKeyToWallet(pwalletMain, Params().GetConsensus()), spendingkey);
|
||||||
AddSpendingKeyToWallet(pwalletMain, Params().GetConsensus()), spendingkey);
|
|
||||||
if (addResult == KeyAlreadyExists && fIgnoreExistingKey) {
|
if (addResult == KeyAlreadyExists && fIgnoreExistingKey) {
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4573,7 +4573,7 @@ boost::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator
|
|||||||
}
|
}
|
||||||
|
|
||||||
SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKey &sk) const {
|
SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKey &sk) const {
|
||||||
auto addr = sk.address();
|
auto addr = sk.address();
|
||||||
if (log){
|
if (log){
|
||||||
LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
|
LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
|
||||||
}
|
}
|
||||||
@@ -4610,7 +4610,14 @@ SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingE
|
|||||||
// 154051200 seconds from epoch is Friday, 26 October 2018 00:00:00 GMT - definitely before Sapling activates
|
// 154051200 seconds from epoch is Friday, 26 October 2018 00:00:00 GMT - definitely before Sapling activates
|
||||||
m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = std::max((int64_t) 154051200, nTime);
|
m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = std::max((int64_t) 154051200, nTime);
|
||||||
}
|
}
|
||||||
|
if (hdKeypath) {
|
||||||
|
m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath = hdKeypath.get();
|
||||||
|
}
|
||||||
|
if (seedFpStr) {
|
||||||
|
uint256 seedFp;
|
||||||
|
seedFp.SetHex(seedFpStr.get());
|
||||||
|
m_wallet->mapSaplingZKeyMetadata[ivk].seedFp = seedFp;
|
||||||
|
}
|
||||||
return KeyAdded;
|
return KeyAdded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1388,12 +1388,21 @@ private:
|
|||||||
CWallet *m_wallet;
|
CWallet *m_wallet;
|
||||||
const Consensus::Params ¶ms;
|
const Consensus::Params ¶ms;
|
||||||
int64_t nTime;
|
int64_t nTime;
|
||||||
|
boost::optional<std::string> hdKeypath; // currently sapling only
|
||||||
|
boost::optional<std::string> seedFpStr; // currently sapling only
|
||||||
bool log;
|
bool log;
|
||||||
public:
|
public:
|
||||||
AddSpendingKeyToWallet(CWallet *wallet, const Consensus::Params ¶ms) :
|
AddSpendingKeyToWallet(CWallet *wallet, const Consensus::Params ¶ms) :
|
||||||
m_wallet(wallet), params(params), nTime(1), log(false) {}
|
m_wallet(wallet), params(params), nTime(1), hdKeypath(boost::none), seedFpStr(boost::none), log(false) {}
|
||||||
AddSpendingKeyToWallet(CWallet *wallet, const Consensus::Params ¶ms, int64_t _nTime, bool _log) :
|
AddSpendingKeyToWallet(
|
||||||
m_wallet(wallet), params(params), nTime(_nTime), log(_log) {}
|
CWallet *wallet,
|
||||||
|
const Consensus::Params ¶ms,
|
||||||
|
int64_t _nTime,
|
||||||
|
boost::optional<std::string> _hdKeypath,
|
||||||
|
boost::optional<std::string> _seedFp,
|
||||||
|
bool _log
|
||||||
|
) : m_wallet(wallet), params(params), nTime(_nTime), hdKeypath(_hdKeypath), seedFpStr(_seedFp), log(_log) {}
|
||||||
|
|
||||||
|
|
||||||
SpendingKeyAddResult operator()(const libzcash::SproutSpendingKey &sk) const;
|
SpendingKeyAddResult operator()(const libzcash::SproutSpendingKey &sk) const;
|
||||||
SpendingKeyAddResult operator()(const libzcash::SaplingExtendedSpendingKey &sk) const;
|
SpendingKeyAddResult operator()(const libzcash::SaplingExtendedSpendingKey &sk) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user