Browse Source

desprout

danger
Duke Leto 4 years ago
parent
commit
2134269e76
  1. 77
      src/gtest/test_keystore.cpp
  2. 14
      src/rpc/misc.cpp
  3. 57
      src/test/rpc_wallet_tests.cpp
  4. 12
      src/txdb.cpp
  5. 34
      src/wallet/crypter.h
  6. 77
      src/wallet/rpcdump.cpp

77
src/gtest/test_keystore.cpp

@ -185,9 +185,6 @@ TEST(keystore_tests, StoreAndRetrieveHDSeedInEncryptedStore) {
// 3) Test adding a new seed to an already-encrypted key store
TestCCryptoKeyStore keyStore2;
// Add a Sprout address so the wallet has something to test when decrypting
ASSERT_TRUE(keyStore2.AddSproutSpendingKey(libzcash::SproutSpendingKey::random()));
ASSERT_TRUE(keyStore2.EncryptKeys(vMasterKey));
ASSERT_TRUE(keyStore2.Unlock(vMasterKey));
@ -201,78 +198,4 @@ TEST(keystore_tests, StoreAndRetrieveHDSeedInEncryptedStore) {
EXPECT_EQ(seed3, seedOut);
}
TEST(keystore_tests, store_and_retrieve_spending_key_in_encrypted_store) {
TestCCryptoKeyStore keyStore;
uint256 r {GetRandHash()};
CKeyingMaterial vMasterKey (r.begin(), r.end());
libzcash::SproutSpendingKey keyOut;
ZCNoteDecryption decOut;
std::set<libzcash::SproutPaymentAddress> addrs;
// 1) Test adding a key to an unencrypted key store, then encrypting it
auto sk = libzcash::SproutSpendingKey::random();
auto addr = sk.address();
EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut));
keyStore.AddSproutSpendingKey(sk);
ASSERT_TRUE(keyStore.HaveSproutSpendingKey(addr));
ASSERT_TRUE(keyStore.GetSproutSpendingKey(addr, keyOut));
ASSERT_EQ(sk, keyOut);
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut));
EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut);
ASSERT_TRUE(keyStore.EncryptKeys(vMasterKey));
ASSERT_TRUE(keyStore.HaveSproutSpendingKey(addr));
ASSERT_FALSE(keyStore.GetSproutSpendingKey(addr, keyOut));
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut));
EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut);
// Unlocking with a random key should fail
uint256 r2 {GetRandHash()};
CKeyingMaterial vRandomKey (r2.begin(), r2.end());
EXPECT_FALSE(keyStore.Unlock(vRandomKey));
// Unlocking with a slightly-modified vMasterKey should fail
CKeyingMaterial vModifiedKey (r.begin(), r.end());
vModifiedKey[0] += 1;
EXPECT_FALSE(keyStore.Unlock(vModifiedKey));
// Unlocking with vMasterKey should succeed
ASSERT_TRUE(keyStore.Unlock(vMasterKey));
ASSERT_TRUE(keyStore.GetSproutSpendingKey(addr, keyOut));
ASSERT_EQ(sk, keyOut);
keyStore.GetSproutPaymentAddresses(addrs);
ASSERT_EQ(1, addrs.size());
ASSERT_EQ(1, addrs.count(addr));
// 2) Test adding a spending key to an already-encrypted key store
auto sk2 = libzcash::SproutSpendingKey::random();
auto addr2 = sk2.address();
EXPECT_FALSE(keyStore.GetNoteDecryptor(addr2, decOut));
keyStore.AddSproutSpendingKey(sk2);
ASSERT_TRUE(keyStore.HaveSproutSpendingKey(addr2));
ASSERT_TRUE(keyStore.GetSproutSpendingKey(addr2, keyOut));
ASSERT_EQ(sk2, keyOut);
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr2, decOut));
EXPECT_EQ(ZCNoteDecryption(sk2.receiving_key()), decOut);
ASSERT_TRUE(keyStore.Lock());
ASSERT_TRUE(keyStore.HaveSproutSpendingKey(addr2));
ASSERT_FALSE(keyStore.GetSproutSpendingKey(addr2, keyOut));
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr2, decOut));
EXPECT_EQ(ZCNoteDecryption(sk2.receiving_key()), decOut);
ASSERT_TRUE(keyStore.Unlock(vMasterKey));
ASSERT_TRUE(keyStore.GetSproutSpendingKey(addr2, keyOut));
ASSERT_EQ(sk2, keyOut);
EXPECT_TRUE(keyStore.GetNoteDecryptor(addr2, decOut));
EXPECT_EQ(ZCNoteDecryption(sk2.receiving_key()), decOut);
keyStore.GetSproutPaymentAddresses(addrs);
ASSERT_EQ(2, addrs.size());
ASSERT_EQ(1, addrs.count(addr));
ASSERT_EQ(1, addrs.count(addr2));
}
#endif

14
src/rpc/misc.cpp

@ -1,5 +1,6 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2019-2020 The Hush developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -594,19 +595,6 @@ class DescribePaymentAddressVisitor : public boost::static_visitor<UniValue>
public:
UniValue operator()(const libzcash::InvalidEncoding &zaddr) const { return UniValue(UniValue::VOBJ); }
UniValue operator()(const libzcash::SproutPaymentAddress &zaddr) const {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("type", "sprout"));
obj.push_back(Pair("payingkey", zaddr.a_pk.GetHex()));
obj.push_back(Pair("transmissionkey", zaddr.pk_enc.GetHex()));
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.push_back(Pair("ismine", pwalletMain->HaveSproutSpendingKey(zaddr)));
}
#endif
return obj;
}
UniValue operator()(const libzcash::SaplingPaymentAddress &zaddr) const {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("type", "sapling"));

57
src/test/rpc_wallet_tests.cpp

@ -1,6 +1,7 @@
// Copyright (c) 2013-2014 The Bitcoin Core developers
// Copyright (c) 2019-2020 The Hush developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// file COPYING or https://www.opensource.org/licenses/mit-license.php
#include "rpc/server.h"
#include "rpc/client.h"
@ -341,38 +342,12 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress)
BOOST_CHECK_THROW(CallRPC("z_validateaddress"), runtime_error);
BOOST_CHECK_THROW(CallRPC("z_validateaddress toomany args"), runtime_error);
// Wallet should be empty
std::set<libzcash::SproutPaymentAddress> addrs;
pwalletMain->GetSproutPaymentAddresses(addrs);
BOOST_CHECK(addrs.size()==0);
// This address is not valid, it belongs to another network
BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress ztaaga95QAPyp1kSQ1hD2kguCpzyMHjxWZqaYDEkzbvo7uYQYAw2S8X4Kx98AvhhofMtQL8PAXKHuZsmhRcanavKRKmdCzk"));
UniValue resultObj = retValue.get_obj();
bool b = find_value(resultObj, "isvalid").get_bool();
BOOST_CHECK_EQUAL(b, false);
// This address is valid, but the spending key is not in this wallet
BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zcfA19SDAKRYHLoRDoShcoz4nPohqWxuHcqg8WAxsiB2jFrrs6k7oSvst3UZvMYqpMNSRBkxBsnyjjngX5L55FxMzLKach8"));
resultObj = retValue.get_obj();
b = find_value(resultObj, "isvalid").get_bool();
BOOST_CHECK_EQUAL(b, true);
BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sprout");
b = find_value(resultObj, "ismine").get_bool();
BOOST_CHECK_EQUAL(b, false);
// Let's import a spending key to the wallet and validate its payment address
BOOST_CHECK_NO_THROW(CallRPC("z_importkey SKxoWv77WGwFnUJitQKNEcD636bL4X5Gd6wWmgaA4Q9x8jZBPJXT"));
BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL"));
resultObj = retValue.get_obj();
b = find_value(resultObj, "isvalid").get_bool();
BOOST_CHECK_EQUAL(b, true);
BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sprout");
b = find_value(resultObj, "ismine").get_bool();
BOOST_CHECK_EQUAL(b, true);
BOOST_CHECK_EQUAL(find_value(resultObj, "payingkey").get_str(), "f5bb3c888ccc9831e3f6ba06e7528e26a312eec3acc1823be8918b6a3a5e20ad");
BOOST_CHECK_EQUAL(find_value(resultObj, "transmissionkey").get_str(), "7a58c7132446564e6b810cf895c20537b3528357dc00150a8e201f491efa9c1a");
// This Sapling address is not valid, it belongs to another network
BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress ztestsapling1knww2nyjc62njkard0jmx7hlsj6twxmxwprn7anvrv4dc2zxanl3nemc0qx2hvplxmd2uau8gyw"));
resultObj = retValue.get_obj();
@ -398,16 +373,6 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet)
{
LOCK2(cs_main, pwalletMain->cs_wallet);
// wallet should be empty
std::set<libzcash::SproutPaymentAddress> addrs;
pwalletMain->GetSproutPaymentAddresses(addrs);
BOOST_CHECK(addrs.size()==0);
// wallet should have one key
libzcash::SproutPaymentAddress addr = pwalletMain->GenerateNewSproutZKey();
pwalletMain->GetSproutPaymentAddresses(addrs);
BOOST_CHECK(addrs.size()==1);
// Set up paths
boost::filesystem::path tmppath = boost::filesystem::temp_directory_path();
boost::filesystem::path tmpfilename = boost::filesystem::unique_path("%%%%%%%%");
@ -429,9 +394,6 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet)
BOOST_CHECK_NO_THROW(CallRPC(string("z_exportwallet ") + tmpfilename.string()));
libzcash::SproutSpendingKey key;
BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, key));
std::string s1 = EncodePaymentAddress(addr);
std::string s2 = EncodeSpendingKey(key);
@ -474,13 +436,13 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
BOOST_CHECK_THROW(CallRPC("z_importwallet toomany args"), runtime_error);
// create a random key locally
auto testSpendingKey = libzcash::SproutSpendingKey::random();
auto testSpendingKey = libzcash::SaplingSpendingKey::random();
auto testPaymentAddress = testSpendingKey.address();
std::string testAddr = EncodePaymentAddress(testPaymentAddress);
std::string testKey = EncodeSpendingKey(testSpendingKey);
// create test data using the random key
std::string format_str = "# Wallet dump created by Komodo v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n"
std::string format_str = "# Wallet dump created by Hush v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n"
"# * Created on 2016-08-12T21:55:36Z\n"
"# * Best block at time of backup was 0 (0de0a3851fef2d433b9b4f51d4342bdd24c5ddd793eb8fba57189f07e9235d52),\n"
"# mined on 2009-01-03T18:15:05Z\n"
@ -504,14 +466,14 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
// wallet should currently be empty
std::set<libzcash::SproutPaymentAddress> addrs;
pwalletMain->GetSproutPaymentAddresses(addrs);
pwalletMain->GetSaplingPaymentAddresses(addrs);
BOOST_CHECK(addrs.size()==0);
// import test data from file into wallet
BOOST_CHECK_NO_THROW(CallRPC(string("z_importwallet ") + path));
// wallet should now have one zkey
pwalletMain->GetSproutPaymentAddresses(addrs);
pwalletMain->GetSaplingPaymentAddresses(addrs);
BOOST_CHECK(addrs.size()==1);
// check that we have the spending key for the address
@ -521,10 +483,11 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
auto addr = boost::get<libzcash::SproutPaymentAddress>(address);
BOOST_CHECK(pwalletMain->HaveSproutSpendingKey(addr));
// Verify the spending key is the same as the test data
libzcash::SproutSpendingKey k;
BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, k));
BOOST_CHECK_EQUAL(testKey, EncodeSpendingKey(k));
//libzcash::SproutSpendingKey k;
//BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, k));
//BOOST_CHECK_EQUAL(testKey, EncodeSpendingKey(k));
}

12
src/txdb.cpp

@ -67,18 +67,6 @@ CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(Get
}
bool CCoinsViewDB::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const {
if (rt == SproutMerkleTree::empty_root()) {
SproutMerkleTree new_tree;
tree = new_tree;
return true;
}
bool read = db.Read(make_pair(DB_SPROUT_ANCHOR, rt), tree);
return read;
}
bool CCoinsViewDB::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const {
if (rt == SaplingMerkleTree::empty_root()) {
SaplingMerkleTree new_tree;

34
src/wallet/crypter.h

@ -1,4 +1,5 @@
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2019-2020 The Hush developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -145,7 +146,7 @@ class CCryptoKeyStore : public CBasicKeyStore
private:
std::pair<uint256, std::vector<unsigned char>> cryptedHDSeed;
CryptedKeyMap mapCryptedKeys;
CryptedSproutSpendingKeyMap mapCryptedSproutSpendingKeys;
//CryptedSproutSpendingKeyMap mapCryptedSproutSpendingKeys;
CryptedSaplingSpendingKeyMap mapCryptedSaplingSpendingKeys;
CKeyingMaterial vMasterKey;
@ -223,37 +224,6 @@ public:
mi++;
}
}
virtual bool AddCryptedSproutSpendingKey(
const libzcash::SproutPaymentAddress &address,
const libzcash::ReceivingKey &rk,
const std::vector<unsigned char> &vchCryptedSecret);
bool AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk);
bool HaveSproutSpendingKey(const libzcash::SproutPaymentAddress &address) const
{
{
LOCK(cs_SpendingKeyStore);
if (!IsCrypted())
return CBasicKeyStore::HaveSproutSpendingKey(address);
return mapCryptedSproutSpendingKeys.count(address) > 0;
}
return false;
}
bool GetSproutSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey &skOut) const;
void GetSproutPaymentAddresses(std::set<libzcash::SproutPaymentAddress> &setAddress) const
{
if (!IsCrypted())
{
CBasicKeyStore::GetSproutPaymentAddresses(setAddress);
return;
}
setAddress.clear();
CryptedSproutSpendingKeyMap::const_iterator mi = mapCryptedSproutSpendingKeys.begin();
while (mi != mapCryptedSproutSpendingKeys.end())
{
setAddress.insert((*mi).first);
mi++;
}
}
//! Sapling
virtual bool AddCryptedSaplingSpendingKey(
const libzcash::SaplingExtendedFullViewingKey &extfvk,

77
src/wallet/rpcdump.cpp

@ -856,48 +856,27 @@ UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& m
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid viewing key");
}
if (boost::get<libzcash::SproutViewingKey>(&viewingkey) == nullptr) {
if (params.size() < 4) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Missing zaddr for Sapling viewing key.");
}
string strAddress = params[3].get_str();
auto address = DecodePaymentAddress(strAddress);
if (!IsValidPaymentAddress(address)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr");
}
auto addr = boost::get<libzcash::SaplingPaymentAddress>(address);
auto ivk = boost::get<libzcash::SaplingIncomingViewingKey>(viewingkey);
if (params.size() < 4) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Missing zaddr for Sapling viewing key.");
}
string strAddress = params[3].get_str();
auto address = DecodePaymentAddress(strAddress);
if (!IsValidPaymentAddress(address)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr");
}
if (pwalletMain->HaveSaplingIncomingViewingKey(addr)) {
if (fIgnoreExistingKey) {
return NullUniValue;
}
} else {
pwalletMain->MarkDirty();
auto addr = boost::get<libzcash::SaplingPaymentAddress>(address);
auto ivk = boost::get<libzcash::SaplingIncomingViewingKey>(viewingkey);
if (!pwalletMain->AddSaplingIncomingViewingKey(ivk, addr)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding viewing key to wallet");
}
if (pwalletMain->HaveSaplingIncomingViewingKey(addr)) {
if (fIgnoreExistingKey) {
return NullUniValue;
}
} else {
auto vkey = boost::get<libzcash::SproutViewingKey>(viewingkey);
auto addr = vkey.address();
if (pwalletMain->HaveSproutSpendingKey(addr)) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this viewing key");
}
// Don't throw error in case a viewing key is already there
if (pwalletMain->HaveSproutViewingKey(addr)) {
if (fIgnoreExistingKey) {
return NullUniValue;
}
} else {
pwalletMain->MarkDirty();
pwalletMain->MarkDirty();
if (!pwalletMain->AddSproutViewingKey(vkey)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding viewing key to wallet");
}
if (!pwalletMain->AddSaplingIncomingViewingKey(ivk, addr)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding viewing key to wallet");
}
}
@ -977,26 +956,12 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& m
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr");
}
if (boost::get<libzcash::SproutPaymentAddress>(&address) == nullptr) {
auto addr = boost::get<libzcash::SaplingPaymentAddress>(address);
libzcash::SaplingIncomingViewingKey ivk;
if(!pwalletMain->GetSaplingIncomingViewingKey(addr, ivk)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold viewing key for this zaddr");
}
return EncodeViewingKey(ivk);
auto addr = boost::get<libzcash::SaplingPaymentAddress>(address);
libzcash::SaplingIncomingViewingKey ivk;
if(!pwalletMain->GetSaplingIncomingViewingKey(addr, ivk)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold viewing key for this zaddr");
}
auto addr = boost::get<libzcash::SproutPaymentAddress>(address);
libzcash::SproutViewingKey vk;
if (!pwalletMain->GetSproutViewingKey(addr, vk)) {
libzcash::SproutSpendingKey k;
if (!pwalletMain->GetSproutSpendingKey(addr, k)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private key or viewing key for this zaddr");
}
vk = k.viewing_key();
}
return EncodeViewingKey(vk);
return EncodeViewingKey(ivk);
}
extern int32_t KOMODO_NSPV;

Loading…
Cancel
Save