From e5eab182b58be527e3e2215f053d642b27bb3003 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 26 Apr 2018 02:51:17 +0100 Subject: [PATCH] Use boost::variant to represent shielded addresses and keys libzcash::PaymentAddress has been renamed to libzcash::SproutPaymentAddress, and a new typedef boost::variant is now libzcash::PaymentAddress. Similarly for ViewingKey and SpendingKey. A new class InvalidEncoding is introduced as the default boost::variant option for each address and key type; it is used during decoding instead of boost::optional. All address and key storage functions in the wallet have been modified to refer specifically to the Sprout types, as they are used very precisely. In most other cases, the more general type is leveraged as much as possible, and we convert to the Sprout type when necessary. This will be subsequently wrapped in, or replaced with, context-specific functions once Sapling types are implemented. --- src/gtest/test_joinsplit.cpp | 18 +-- src/gtest/test_keystore.cpp | 24 ++-- src/gtest/test_paymentdisclosure.cpp | 4 +- src/gtest/test_transaction.cpp | 4 +- src/gtest/test_validation.cpp | 2 +- src/key_io.cpp | 108 +++++++++++++----- src/key_io.h | 7 +- src/keystore.cpp | 12 +- src/keystore.h | 42 +++---- src/paymentdisclosure.h | 6 +- src/rpcmisc.cpp | 7 +- src/test/coins_tests.cpp | 4 +- src/test/key_tests.cpp | 12 +- src/test/rpc_wallet_tests.cpp | 35 +++--- src/test/transaction_tests.cpp | 4 +- src/utiltest.cpp | 14 +-- src/utiltest.h | 6 +- .../asyncrpcoperation_mergetoaddress.cpp | 22 ++-- src/wallet/asyncrpcoperation_mergetoaddress.h | 2 +- src/wallet/asyncrpcoperation_sendmany.cpp | 31 ++--- .../asyncrpcoperation_shieldcoinbase.cpp | 10 +- src/wallet/crypter.cpp | 18 +-- src/wallet/crypter.h | 10 +- src/wallet/gtest/test_wallet.cpp | 52 ++++----- src/wallet/gtest/test_wallet_zkeys.cpp | 42 ++++--- src/wallet/rpcdisclosure.cpp | 2 +- src/wallet/rpcdump.cpp | 42 ++++--- src/wallet/rpcwallet.cpp | 85 +++++++++----- src/wallet/wallet.cpp | 30 ++--- src/wallet/wallet.h | 30 ++--- src/wallet/walletdb.cpp | 18 +-- src/wallet/walletdb.h | 8 +- src/zcash/Address.cpp | 31 +++-- src/zcash/Address.hpp | 54 ++++++--- src/zcash/JoinSplit.cpp | 4 +- src/zcash/JoinSplit.hpp | 8 +- src/zcash/Note.cpp | 4 +- src/zcash/Note.hpp | 4 +- src/zcash/circuit/note.tcc | 2 +- src/zcbenchmarks.cpp | 6 +- 40 files changed, 488 insertions(+), 336 deletions(-) diff --git a/src/gtest/test_joinsplit.cpp b/src/gtest/test_joinsplit.cpp index a713fe7dd..c7f4577a3 100644 --- a/src/gtest/test_joinsplit.cpp +++ b/src/gtest/test_joinsplit.cpp @@ -25,8 +25,8 @@ void test_full_api(ZCJoinSplit* js) auto verifier = libzcash::ProofVerifier::Strict(); // The recipient's information. - SpendingKey recipient_key = SpendingKey::random(); - PaymentAddress recipient_addr = recipient_key.address(); + SproutSpendingKey recipient_key = SproutSpendingKey::random(); + SproutPaymentAddress recipient_addr = recipient_key.address(); // Create the commitment tree ZCIncrementalMerkleTree tree; @@ -122,8 +122,8 @@ void test_full_api(ZCJoinSplit* js) JSInput(witness_recipient, decrypted_note, recipient_key) }; - SpendingKey second_recipient = SpendingKey::random(); - PaymentAddress second_addr = second_recipient.address(); + SproutSpendingKey second_recipient = SproutSpendingKey::random(); + SproutPaymentAddress second_addr = second_recipient.address(); boost::array outputs = { JSOutput(second_addr, 9), @@ -317,8 +317,8 @@ TEST(joinsplit, full_api_test) std::vector witnesses; ZCIncrementalMerkleTree tree; increment_note_witnesses(uint256(), witnesses, tree); - SpendingKey sk = SpendingKey::random(); - PaymentAddress addr = sk.address(); + SproutSpendingKey sk = SproutSpendingKey::random(); + SproutPaymentAddress addr = sk.address(); SproutNote note1(addr.a_pk, 100, random_uint256(), random_uint256()); increment_note_witnesses(note1.cm(), witnesses, tree); SproutNote note2(addr.a_pk, 100, random_uint256(), random_uint256()); @@ -422,7 +422,7 @@ TEST(joinsplit, full_api_test) // Wrong secret key invokeAPIFailure(params, { - JSInput(witnesses[1], note1, SpendingKey::random()), + JSInput(witnesses[1], note1, SproutSpendingKey::random()), JSInput() }, { @@ -519,7 +519,7 @@ TEST(joinsplit, note_plaintexts) uint256 a_pk = PRF_addr_a_pk(a_sk); uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk); uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc); - PaymentAddress addr_pk(a_pk, pk_enc); + SproutPaymentAddress addr_pk(a_pk, pk_enc); uint256 h_sig; @@ -572,7 +572,7 @@ TEST(joinsplit, note_class) uint256 a_pk = PRF_addr_a_pk(a_sk); uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk); uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc); - PaymentAddress addr_pk(a_pk, pk_enc); + SproutPaymentAddress addr_pk(a_pk, pk_enc); SproutNote note(a_pk, 1945813, diff --git a/src/gtest/test_keystore.cpp b/src/gtest/test_keystore.cpp index 76b57cd9f..22e009e76 100644 --- a/src/gtest/test_keystore.cpp +++ b/src/gtest/test_keystore.cpp @@ -9,13 +9,13 @@ TEST(keystore_tests, store_and_retrieve_spending_key) { CBasicKeyStore keyStore; - libzcash::SpendingKey skOut; + libzcash::SproutSpendingKey skOut; - std::set addrs; + std::set addrs; keyStore.GetPaymentAddresses(addrs); EXPECT_EQ(0, addrs.size()); - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto addr = sk.address(); // Sanity-check: we can't get a key we haven't added @@ -36,7 +36,7 @@ TEST(keystore_tests, store_and_retrieve_note_decryptor) { CBasicKeyStore keyStore; ZCNoteDecryption decOut; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto addr = sk.address(); EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut)); @@ -48,11 +48,11 @@ TEST(keystore_tests, store_and_retrieve_note_decryptor) { TEST(keystore_tests, StoreAndRetrieveViewingKey) { CBasicKeyStore keyStore; - libzcash::ViewingKey vkOut; - libzcash::SpendingKey skOut; + libzcash::SproutViewingKey vkOut; + libzcash::SproutSpendingKey skOut; ZCNoteDecryption decOut; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto vk = sk.viewing_key(); auto addr = sk.address(); @@ -66,7 +66,7 @@ TEST(keystore_tests, StoreAndRetrieveViewingKey) { EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut)); // and we can't find it in our list of addresses - std::set addresses; + std::set addresses; keyStore.GetPaymentAddresses(addresses); EXPECT_FALSE(addresses.count(addr)); @@ -115,12 +115,12 @@ TEST(keystore_tests, store_and_retrieve_spending_key_in_encrypted_store) { TestCCryptoKeyStore keyStore; uint256 r {GetRandHash()}; CKeyingMaterial vMasterKey (r.begin(), r.end()); - libzcash::SpendingKey keyOut; + libzcash::SproutSpendingKey keyOut; ZCNoteDecryption decOut; - std::set addrs; + std::set addrs; // 1) Test adding a key to an unencrypted key store, then encrypting it - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto addr = sk.address(); EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut)); @@ -157,7 +157,7 @@ TEST(keystore_tests, store_and_retrieve_spending_key_in_encrypted_store) { ASSERT_EQ(1, addrs.count(addr)); // 2) Test adding a spending key to an already-encrypted key store - auto sk2 = libzcash::SpendingKey::random(); + auto sk2 = libzcash::SproutSpendingKey::random(); auto addr2 = sk2.address(); EXPECT_FALSE(keyStore.GetNoteDecryptor(addr2, decOut)); diff --git a/src/gtest/test_paymentdisclosure.cpp b/src/gtest/test_paymentdisclosure.cpp index ddab3c7e6..e9768a6fd 100644 --- a/src/gtest/test_paymentdisclosure.cpp +++ b/src/gtest/test_paymentdisclosure.cpp @@ -120,7 +120,7 @@ TEST(paymentdisclosure, mainnet) { PaymentDisclosureInfo info; info.esk = random_uint256(); info.joinSplitPrivKey = joinSplitPrivKey; - info.zaddr = libzcash::SpendingKey::random().address(); + info.zaddr = libzcash::SproutSpendingKey::random().address(); ASSERT_TRUE(mydb.Put(key, info)); // Retrieve info from test database into new local variable and test it matches @@ -131,7 +131,7 @@ TEST(paymentdisclosure, mainnet) { // Modify this local variable and confirm it no longer matches info2.esk = random_uint256(); info2.joinSplitPrivKey = random_uint256(); - info2.zaddr = libzcash::SpendingKey::random().address(); + info2.zaddr = libzcash::SproutSpendingKey::random().address(); ASSERT_NE(info, info2); // Using the payment info object, let's create a dummy payload diff --git a/src/gtest/test_transaction.cpp b/src/gtest/test_transaction.cpp index 0f78fcb39..ee674c6e2 100644 --- a/src/gtest/test_transaction.cpp +++ b/src/gtest/test_transaction.cpp @@ -12,8 +12,8 @@ TEST(Transaction, JSDescriptionRandomized) { // construct a merkle tree ZCIncrementalMerkleTree merkleTree; - libzcash::SpendingKey k = libzcash::SpendingKey::random(); - libzcash::PaymentAddress addr = k.address(); + libzcash::SproutSpendingKey k = libzcash::SproutSpendingKey::random(); + libzcash::SproutPaymentAddress addr = k.address(); libzcash::SproutNote note(addr.a_pk, 100, uint256(), uint256()); diff --git a/src/gtest/test_validation.cpp b/src/gtest/test_validation.cpp index 8609c93ba..5059a2046 100644 --- a/src/gtest/test_validation.cpp +++ b/src/gtest/test_validation.cpp @@ -87,7 +87,7 @@ TEST(Validation, ContextualCheckInputsPassesWithCoinbase) { } TEST(Validation, ReceivedBlockTransactions) { - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); // Create a fake genesis block CBlock block1; diff --git a/src/key_io.cpp b/src/key_io.cpp index 77d63cca4..a7f614f25 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -67,6 +67,70 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par } return CNoDestination(); } + +class PaymentAddressEncoder : public boost::static_visitor +{ +private: + const CChainParams& m_params; + +public: + PaymentAddressEncoder(const CChainParams& params) : m_params(params) {} + + std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const + { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << zaddr; + std::vector data = m_params.Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS); + data.insert(data.end(), ss.begin(), ss.end()); + return EncodeBase58Check(data); + } + + std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; } +}; + +class ViewingKeyEncoder : public boost::static_visitor +{ +private: + const CChainParams& m_params; + +public: + ViewingKeyEncoder(const CChainParams& params) : m_params(params) {} + + std::string operator()(const libzcash::SproutViewingKey& vk) const + { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << vk; + std::vector data = m_params.Base58Prefix(CChainParams::ZCVIEWING_KEY); + data.insert(data.end(), ss.begin(), ss.end()); + std::string ret = EncodeBase58Check(data); + memory_cleanse(data.data(), data.size()); + return ret; + } + + std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; } +}; + +class SpendingKeyEncoder : public boost::static_visitor +{ +private: + const CChainParams& m_params; + +public: + SpendingKeyEncoder(const CChainParams& params) : m_params(params) {} + + std::string operator()(const libzcash::SproutSpendingKey& zkey) const + { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << zkey; + std::vector data = m_params.Base58Prefix(CChainParams::ZCSPENDING_KEY); + data.insert(data.end(), ss.begin(), ss.end()); + std::string ret = EncodeBase58Check(data); + memory_cleanse(data.data(), data.size()); + return ret; + } + + std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; } +}; } // namespace CKey DecodeSecret(const std::string& str) @@ -167,14 +231,10 @@ bool IsValidDestinationString(const std::string& str) std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr) { - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << zaddr; - std::vector data = Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS); - data.insert(data.end(), ss.begin(), ss.end()); - return EncodeBase58Check(data); + return boost::apply_visitor(PaymentAddressEncoder(Params()), zaddr); } -boost::optional DecodePaymentAddress(const std::string& str) +libzcash::PaymentAddress DecodePaymentAddress(const std::string& str) { std::vector data; if (DecodeBase58Check(str, data)) { @@ -183,26 +243,24 @@ boost::optional DecodePaymentAddress(const std::string std::equal(zaddr_prefix.begin(), zaddr_prefix.end(), data.begin())) { CSerializeData serialized(data.begin() + zaddr_prefix.size(), data.end()); CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); - libzcash::PaymentAddress ret; + libzcash::SproutPaymentAddress ret; ss >> ret; return ret; } } - return boost::none; + return libzcash::InvalidEncoding(); +} + +bool IsValidPaymentAddressString(const std::string& str) { + return IsValidPaymentAddress(DecodePaymentAddress(str)); } std::string EncodeViewingKey(const libzcash::ViewingKey& vk) { - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << vk; - std::vector data = Params().Base58Prefix(CChainParams::ZCVIEWING_KEY); - data.insert(data.end(), ss.begin(), ss.end()); - std::string ret = EncodeBase58Check(data); - memory_cleanse(data.data(), data.size()); - return ret; + return boost::apply_visitor(ViewingKeyEncoder(Params()), vk); } -boost::optional DecodeViewingKey(const std::string& str) +libzcash::ViewingKey DecodeViewingKey(const std::string& str) { std::vector data; if (DecodeBase58Check(str, data)) { @@ -211,7 +269,7 @@ boost::optional DecodeViewingKey(const std::string& str) std::equal(vk_prefix.begin(), vk_prefix.end(), data.begin())) { CSerializeData serialized(data.begin() + vk_prefix.size(), data.end()); CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); - libzcash::ViewingKey ret; + libzcash::SproutViewingKey ret; ss >> ret; memory_cleanse(serialized.data(), serialized.size()); memory_cleanse(data.data(), data.size()); @@ -219,21 +277,15 @@ boost::optional DecodeViewingKey(const std::string& str) } } memory_cleanse(data.data(), data.size()); - return boost::none; + return libzcash::InvalidEncoding(); } std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey) { - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << zkey; - std::vector data = Params().Base58Prefix(CChainParams::ZCSPENDING_KEY); - data.insert(data.end(), ss.begin(), ss.end()); - std::string ret = EncodeBase58Check(data); - memory_cleanse(data.data(), data.size()); - return ret; + return boost::apply_visitor(SpendingKeyEncoder(Params()), zkey); } -boost::optional DecodeSpendingKey(const std::string& str) +libzcash::SpendingKey DecodeSpendingKey(const std::string& str) { std::vector data; if (DecodeBase58Check(str, data)) { @@ -242,7 +294,7 @@ boost::optional DecodeSpendingKey(const std::string& str) std::equal(zkey_prefix.begin(), zkey_prefix.end(), data.begin())) { CSerializeData serialized(data.begin() + zkey_prefix.size(), data.end()); CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); - libzcash::SpendingKey ret; + libzcash::SproutSpendingKey ret; ss >> ret; memory_cleanse(serialized.data(), serialized.size()); memory_cleanse(data.data(), data.size()); @@ -250,5 +302,5 @@ boost::optional DecodeSpendingKey(const std::string& str) } } memory_cleanse(data.data(), data.size()); - return boost::none; + return libzcash::InvalidEncoding(); } diff --git a/src/key_io.h b/src/key_io.h index dd95976a3..c01d1d836 100644 --- a/src/key_io.h +++ b/src/key_io.h @@ -29,12 +29,13 @@ bool IsValidDestinationString(const std::string& str); bool IsValidDestinationString(const std::string& str, const CChainParams& params); std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr); -boost::optional DecodePaymentAddress(const std::string& str); +libzcash::PaymentAddress DecodePaymentAddress(const std::string& str); +bool IsValidPaymentAddressString(const std::string& str); std::string EncodeViewingKey(const libzcash::ViewingKey& vk); -boost::optional DecodeViewingKey(const std::string& str); +libzcash::ViewingKey DecodeViewingKey(const std::string& str); std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey); -boost::optional DecodeSpendingKey(const std::string& str); +libzcash::SpendingKey DecodeSpendingKey(const std::string& str); #endif // BITCOIN_KEYIO_H diff --git a/src/keystore.cpp b/src/keystore.cpp index 323fe710c..edab1e50a 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -84,7 +84,7 @@ bool CBasicKeyStore::HaveWatchOnly() const return (!setWatchOnly.empty()); } -bool CBasicKeyStore::AddSpendingKey(const libzcash::SpendingKey &sk) +bool CBasicKeyStore::AddSpendingKey(const libzcash::SproutSpendingKey &sk) { LOCK(cs_SpendingKeyStore); auto address = sk.address(); @@ -93,7 +93,7 @@ bool CBasicKeyStore::AddSpendingKey(const libzcash::SpendingKey &sk) return true; } -bool CBasicKeyStore::AddViewingKey(const libzcash::ViewingKey &vk) +bool CBasicKeyStore::AddViewingKey(const libzcash::SproutViewingKey &vk) { LOCK(cs_SpendingKeyStore); auto address = vk.address(); @@ -102,21 +102,21 @@ bool CBasicKeyStore::AddViewingKey(const libzcash::ViewingKey &vk) return true; } -bool CBasicKeyStore::RemoveViewingKey(const libzcash::ViewingKey &vk) +bool CBasicKeyStore::RemoveViewingKey(const libzcash::SproutViewingKey &vk) { LOCK(cs_SpendingKeyStore); mapViewingKeys.erase(vk.address()); return true; } -bool CBasicKeyStore::HaveViewingKey(const libzcash::PaymentAddress &address) const +bool CBasicKeyStore::HaveViewingKey(const libzcash::SproutPaymentAddress &address) const { LOCK(cs_SpendingKeyStore); return mapViewingKeys.count(address) > 0; } -bool CBasicKeyStore::GetViewingKey(const libzcash::PaymentAddress &address, - libzcash::ViewingKey &vkOut) const +bool CBasicKeyStore::GetViewingKey(const libzcash::SproutPaymentAddress &address, + libzcash::SproutViewingKey &vkOut) const { LOCK(cs_SpendingKeyStore); ViewingKeyMap::const_iterator mi = mapViewingKeys.find(address); diff --git a/src/keystore.h b/src/keystore.h index b1ad32a42..3195c40b3 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -49,26 +49,26 @@ public: virtual bool HaveWatchOnly() const =0; //! Add a spending key to the store. - virtual bool AddSpendingKey(const libzcash::SpendingKey &sk) =0; + virtual bool AddSpendingKey(const libzcash::SproutSpendingKey &sk) =0; //! Check whether a spending key corresponding to a given payment address is present in the store. - virtual bool HaveSpendingKey(const libzcash::PaymentAddress &address) const =0; - virtual bool GetSpendingKey(const libzcash::PaymentAddress &address, libzcash::SpendingKey& skOut) const =0; - virtual void GetPaymentAddresses(std::set &setAddress) const =0; + virtual bool HaveSpendingKey(const libzcash::SproutPaymentAddress &address) const =0; + virtual bool GetSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey& skOut) const =0; + virtual void GetPaymentAddresses(std::set &setAddress) const =0; //! Support for viewing keys - virtual bool AddViewingKey(const libzcash::ViewingKey &vk) =0; - virtual bool RemoveViewingKey(const libzcash::ViewingKey &vk) =0; - virtual bool HaveViewingKey(const libzcash::PaymentAddress &address) const =0; - virtual bool GetViewingKey(const libzcash::PaymentAddress &address, libzcash::ViewingKey& vkOut) const =0; + virtual bool AddViewingKey(const libzcash::SproutViewingKey &vk) =0; + virtual bool RemoveViewingKey(const libzcash::SproutViewingKey &vk) =0; + virtual bool HaveViewingKey(const libzcash::SproutPaymentAddress &address) const =0; + virtual bool GetViewingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutViewingKey& vkOut) const =0; }; typedef std::map KeyMap; typedef std::map ScriptMap; typedef std::set WatchOnlySet; -typedef std::map SpendingKeyMap; -typedef std::map ViewingKeyMap; -typedef std::map NoteDecryptorMap; +typedef std::map SpendingKeyMap; +typedef std::map ViewingKeyMap; +typedef std::map NoteDecryptorMap; /** Basic key store, that keeps keys in an address->secret map */ class CBasicKeyStore : public CKeyStore @@ -127,8 +127,8 @@ public: virtual bool HaveWatchOnly(const CScript &dest) const; virtual bool HaveWatchOnly() const; - bool AddSpendingKey(const libzcash::SpendingKey &sk); - bool HaveSpendingKey(const libzcash::PaymentAddress &address) const + bool AddSpendingKey(const libzcash::SproutSpendingKey &sk); + bool HaveSpendingKey(const libzcash::SproutPaymentAddress &address) const { bool result; { @@ -137,7 +137,7 @@ public: } return result; } - bool GetSpendingKey(const libzcash::PaymentAddress &address, libzcash::SpendingKey &skOut) const + bool GetSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey &skOut) const { { LOCK(cs_SpendingKeyStore); @@ -150,7 +150,7 @@ public: } return false; } - bool GetNoteDecryptor(const libzcash::PaymentAddress &address, ZCNoteDecryption &decOut) const + bool GetNoteDecryptor(const libzcash::SproutPaymentAddress &address, ZCNoteDecryption &decOut) const { { LOCK(cs_SpendingKeyStore); @@ -163,7 +163,7 @@ public: } return false; } - void GetPaymentAddresses(std::set &setAddress) const + void GetPaymentAddresses(std::set &setAddress) const { setAddress.clear(); { @@ -183,14 +183,14 @@ public: } } - virtual bool AddViewingKey(const libzcash::ViewingKey &vk); - virtual bool RemoveViewingKey(const libzcash::ViewingKey &vk); - virtual bool HaveViewingKey(const libzcash::PaymentAddress &address) const; - virtual bool GetViewingKey(const libzcash::PaymentAddress &address, libzcash::ViewingKey& vkOut) const; + virtual bool AddViewingKey(const libzcash::SproutViewingKey &vk); + virtual bool RemoveViewingKey(const libzcash::SproutViewingKey &vk); + virtual bool HaveViewingKey(const libzcash::SproutPaymentAddress &address) const; + virtual bool GetViewingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutViewingKey& vkOut) const; }; typedef std::vector > CKeyingMaterial; typedef std::map > > CryptedKeyMap; -typedef std::map > CryptedSpendingKeyMap; +typedef std::map > CryptedSpendingKeyMap; #endif // BITCOIN_KEYSTORE_H diff --git a/src/paymentdisclosure.h b/src/paymentdisclosure.h index b3681affc..eea0fda10 100644 --- a/src/paymentdisclosure.h +++ b/src/paymentdisclosure.h @@ -38,12 +38,12 @@ struct PaymentDisclosureInfo { uint256 joinSplitPrivKey; // primitives/transaction.h // ed25519 - not tied to implementation e.g. libsodium, see ed25519 rfc - libzcash::PaymentAddress zaddr; + libzcash::SproutPaymentAddress zaddr; PaymentDisclosureInfo() : version(PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL) { } - PaymentDisclosureInfo(uint8_t v, uint256 esk, uint256 key, libzcash::PaymentAddress zaddr) : version(v), esk(esk), joinSplitPrivKey(key), zaddr(zaddr) { } + PaymentDisclosureInfo(uint8_t v, uint256 esk, uint256 key, libzcash::SproutPaymentAddress zaddr) : version(v), esk(esk), joinSplitPrivKey(key), zaddr(zaddr) { } ADD_SERIALIZE_METHODS; @@ -75,7 +75,7 @@ struct PaymentDisclosurePayload { uint256 txid; // primitives/transaction.h uint64_t js; // Index into CTransaction.vjoinsplit uint8_t n; // Index into JSDescription fields of length ZC_NUM_JS_OUTPUTS - libzcash::PaymentAddress zaddr; // zcash/Address.hpp + libzcash::SproutPaymentAddress zaddr; // zcash/Address.hpp std::string message; // parameter to RPC call ADD_SERIALIZE_METHODS; diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 473918c9c..6359e507c 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -239,9 +239,12 @@ UniValue z_validateaddress(const UniValue& params, bool fHelp) std::string payingKey, transmissionKey; string strAddress = params[0].get_str(); - auto isValid = DecodePaymentAddress(strAddress); + auto address = DecodePaymentAddress(strAddress); + bool isValid = IsValidPaymentAddress(address); if (isValid) { - libzcash::PaymentAddress addr = *isValid; + // TODO: Add Sapling support + assert(boost::get(&address) != nullptr); + libzcash::SproutPaymentAddress addr = boost::get(address); #ifdef ENABLE_WALLET isMine = pwalletMain->HaveSpendingKey(addr); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index c1bd8a553..837ddea81 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -247,8 +247,8 @@ public: uint256 appendRandomCommitment(ZCIncrementalMerkleTree &tree) { - libzcash::SpendingKey k = libzcash::SpendingKey::random(); - libzcash::PaymentAddress addr = k.address(); + libzcash::SproutSpendingKey k = libzcash::SproutSpendingKey::random(); + libzcash::SproutPaymentAddress addr = k.address(); libzcash::SproutNote note(addr.a_pk, 0, uint256(), uint256()); diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 890d126f9..9c7385419 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(key_test1) BOOST_AUTO_TEST_CASE(zc_address_test) { for (size_t i = 0; i < 1000; i++) { - auto sk = SpendingKey::random(); + auto sk = SproutSpendingKey::random(); { string sk_string = EncodeSpendingKey(sk); @@ -196,8 +196,9 @@ BOOST_AUTO_TEST_CASE(zc_address_test) BOOST_CHECK(sk_string[1] == 'K'); auto spendingkey2 = DecodeSpendingKey(sk_string); - BOOST_ASSERT(static_cast(spendingkey2)); - SpendingKey sk2 = *spendingkey2; + BOOST_CHECK(IsValidSpendingKey(spendingkey2)); + BOOST_ASSERT(boost::get(&spendingkey2) != nullptr); + auto sk2 = boost::get(spendingkey2); BOOST_CHECK(sk.inner() == sk2.inner()); } { @@ -209,9 +210,10 @@ BOOST_AUTO_TEST_CASE(zc_address_test) BOOST_CHECK(addr_string[1] == 'c'); auto paymentaddr2 = DecodePaymentAddress(addr_string); - BOOST_ASSERT(static_cast(paymentaddr2)); + BOOST_ASSERT(IsValidPaymentAddress(paymentaddr2)); - PaymentAddress addr2 = *paymentaddr2; + BOOST_ASSERT(boost::get(&paymentaddr2) != nullptr); + auto addr2 = boost::get(paymentaddr2); BOOST_CHECK(addr.a_pk == addr2.a_pk); BOOST_CHECK(addr.pk_enc == addr2.pk_enc); } diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 0e09e5b14..47c85722a 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress) BOOST_CHECK_THROW(CallRPC("z_validateaddress toomany args"), runtime_error); // Wallet should be empty - std::set addrs; + std::set addrs; pwalletMain->GetPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==0); @@ -381,12 +381,15 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet) LOCK2(cs_main, pwalletMain->cs_wallet); // wallet should be empty - std::set addrs; + std::set addrs; pwalletMain->GetPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==0); // wallet should have one key - auto addr = pwalletMain->GenerateNewZKey(); + auto address = pwalletMain->GenerateNewZKey(); + BOOST_CHECK(IsValidPaymentAddress(address)); + BOOST_ASSERT(boost::get(&address) != nullptr); + auto addr = boost::get(address); pwalletMain->GetPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==1); @@ -411,7 +414,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet) BOOST_CHECK_NO_THROW(CallRPC(string("z_exportwallet ") + tmpfilename.string())); - libzcash::SpendingKey key; + libzcash::SproutSpendingKey key; BOOST_CHECK(pwalletMain->GetSpendingKey(addr, key)); std::string s1 = EncodePaymentAddress(addr); @@ -456,7 +459,7 @@ 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::SpendingKey::random(); + auto testSpendingKey = libzcash::SproutSpendingKey::random(); auto testPaymentAddress = testSpendingKey.address(); std::string testAddr = EncodePaymentAddress(testPaymentAddress); std::string testKey = EncodeSpendingKey(testSpendingKey); @@ -485,7 +488,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) file << std::flush; // wallet should currently be empty - std::set addrs; + std::set addrs; pwalletMain->GetPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==0); @@ -497,11 +500,14 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) BOOST_CHECK(addrs.size()==1); // check that we have the spending key for the address - auto addr = *DecodePaymentAddress(testAddr); + auto address = DecodePaymentAddress(testAddr); + BOOST_CHECK(IsValidPaymentAddress(address)); + BOOST_ASSERT(boost::get(&address) != nullptr); + auto addr = boost::get(address); BOOST_CHECK(pwalletMain->HaveSpendingKey(addr)); // Verify the spending key is the same as the test data - libzcash::SpendingKey k; + libzcash::SproutSpendingKey k; BOOST_CHECK(pwalletMain->GetSpendingKey(addr, k)); BOOST_CHECK_EQUAL(testKey, EncodeSpendingKey(k)); } @@ -526,7 +532,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) BOOST_CHECK_THROW(CallRPC("z_exportkey toomany args"), runtime_error); // error if invalid args - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); std::string prefix = std::string("z_importkey ") + EncodeSpendingKey(sk) + " yes "; BOOST_CHECK_THROW(CallRPC(prefix + "-1"), runtime_error); BOOST_CHECK_THROW(CallRPC(prefix + "2147483647"), runtime_error); // allowed, but > height of active chain tip @@ -534,14 +540,14 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) BOOST_CHECK_THROW(CallRPC(prefix + "100badchars"), runtime_error); // wallet should currently be empty - std::set addrs; + std::set addrs; pwalletMain->GetPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==0); // verify import and export key for (int i = 0; i < n1; i++) { // create a random key locally - auto testSpendingKey = libzcash::SpendingKey::random(); + auto testSpendingKey = libzcash::SproutSpendingKey::random(); auto testPaymentAddress = testSpendingKey.address(); std::string testAddr = EncodePaymentAddress(testPaymentAddress); std::string testKey = EncodeSpendingKey(testSpendingKey); @@ -590,7 +596,10 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) // Add one more address BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getnewaddress")); std::string newaddress = retValue.get_str(); - auto newAddr = *DecodePaymentAddress(newaddress); + auto address = DecodePaymentAddress(newaddress); + BOOST_CHECK(IsValidPaymentAddress(address)); + BOOST_ASSERT(boost::get(&address) != nullptr); + auto newAddr = boost::get(address); BOOST_CHECK(pwalletMain->HaveSpendingKey(newAddr)); // Check if too many args @@ -1217,7 +1226,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_encrypted_wallet_zkeys) int n = 100; // wallet should currently be empty - std::set addrs; + std::set addrs; pwalletMain->GetPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==0); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 4702f10e5..fa1238edc 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -342,8 +342,8 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification) // construct a merkle tree ZCIncrementalMerkleTree merkleTree; - libzcash::SpendingKey k = libzcash::SpendingKey::random(); - libzcash::PaymentAddress addr = k.address(); + auto k = libzcash::SproutSpendingKey::random(); + auto addr = k.address(); libzcash::SproutNote note(addr.a_pk, 100, uint256(), uint256()); diff --git a/src/utiltest.cpp b/src/utiltest.cpp index e1b7b8275..6f43afbfa 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -7,7 +7,7 @@ #include "consensus/upgrades.h" CWalletTx GetValidReceive(ZCJoinSplit& params, - const libzcash::SpendingKey& sk, CAmount value, + const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs) { CMutableTransaction mtx; mtx.nVersion = 2; // Enable JoinSplits @@ -62,7 +62,7 @@ CWalletTx GetValidReceive(ZCJoinSplit& params, } libzcash::SproutNote GetNote(ZCJoinSplit& params, - const libzcash::SpendingKey& sk, + const libzcash::SproutSpendingKey& sk, const CTransaction& tx, size_t js, size_t n) { ZCNoteDecryption decryptor {sk.receiving_key()}; auto hSig = tx.vjoinsplit[js].h_sig(params, tx.joinSplitPubKey); @@ -76,7 +76,7 @@ libzcash::SproutNote GetNote(ZCJoinSplit& params, } CWalletTx GetValidSpend(ZCJoinSplit& params, - const libzcash::SpendingKey& sk, + const libzcash::SproutSpendingKey& sk, const libzcash::SproutNote& note, CAmount value) { CMutableTransaction mtx; mtx.vout.resize(2); @@ -97,12 +97,12 @@ CWalletTx GetValidSpend(ZCJoinSplit& params, { if (note.value() > value) { - libzcash::SpendingKey dummykey = libzcash::SpendingKey::random(); - libzcash::PaymentAddress dummyaddr = dummykey.address(); + libzcash::SproutSpendingKey dummykey = libzcash::SproutSpendingKey::random(); + libzcash::SproutPaymentAddress dummyaddr = dummykey.address(); dummyout = libzcash::JSOutput(dummyaddr, note.value() - value); } else if (note.value() < value) { - libzcash::SpendingKey dummykey = libzcash::SpendingKey::random(); - libzcash::PaymentAddress dummyaddr = dummykey.address(); + libzcash::SproutSpendingKey dummykey = libzcash::SproutSpendingKey::random(); + libzcash::SproutPaymentAddress dummyaddr = dummykey.address(); libzcash::SproutNote dummynote(dummyaddr.a_pk, (value - note.value()), uint256(), uint256()); tree.append(dummynote.cm()); dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey); diff --git a/src/utiltest.h b/src/utiltest.h index d9da2a1de..722930609 100644 --- a/src/utiltest.h +++ b/src/utiltest.h @@ -8,11 +8,11 @@ #include "zcash/NoteEncryption.hpp" CWalletTx GetValidReceive(ZCJoinSplit& params, - const libzcash::SpendingKey& sk, CAmount value, + const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs); libzcash::SproutNote GetNote(ZCJoinSplit& params, - const libzcash::SpendingKey& sk, + const libzcash::SproutSpendingKey& sk, const CTransaction& tx, size_t js, size_t n); CWalletTx GetValidSpend(ZCJoinSplit& params, - const libzcash::SpendingKey& sk, + const libzcash::SproutSpendingKey& sk, const libzcash::SproutNote& note, CAmount value); diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index aa8abf782..4ea230c4f 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -80,9 +80,11 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress( if (!isToTaddr_) { auto address = DecodePaymentAddress(std::get<0>(recipient)); - if (address) { + if (IsValidPaymentAddress(address)) { isToZaddr_ = true; - toPaymentAddress_ = *address; + // TODO: Add Sapling support. For now, ensure we can later convert freely. + assert(boost::get(&address) != nullptr); + toPaymentAddress_ = address; } else { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address"); } @@ -307,7 +309,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() info.vpub_old = sendAmount; info.vpub_new = 0; - JSOutput jso = JSOutput(toPaymentAddress_, sendAmount); + JSOutput jso = JSOutput(boost::get(toPaymentAddress_), sendAmount); if (hexMemo.size() > 0) { jso.memo = get_memo_from_hex_string(hexMemo); } @@ -326,6 +328,8 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() // Copy zinputs to more flexible containers std::deque zInputsDeque; for (auto o : noteInputs_) { + // TODO: Add Sapling support. For now, ensure we can later convert freely. + assert(boost::get(&std::get<3>(o)) != nullptr); zInputsDeque.push_back(o); } @@ -365,8 +369,8 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() // At this point, we are guaranteed to have at least one input note. // Use address of first input note as the temporary change address. - SpendingKey changeKey = std::get<3>(zInputsDeque.front()); - PaymentAddress changeAddress = changeKey.address(); + SproutSpendingKey changeKey = boost::get(std::get<3>(zInputsDeque.front())); + SproutPaymentAddress changeAddress = changeKey.address(); CAmount vpubOldTarget = 0; CAmount vpubNewTarget = 0; @@ -481,7 +485,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() // Consume spendable non-change notes // std::vector vInputNotes; - std::vector vInputZKeys; + std::vector vInputZKeys; std::vector vOutPoints; std::vector> vInputWitnesses; uint256 inputAnchor; @@ -491,7 +495,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() JSOutPoint jso = std::get<0>(t); SproutNote note = std::get<1>(t); CAmount noteFunds = std::get<2>(t); - SpendingKey zkey = std::get<3>(t); + SproutSpendingKey zkey = boost::get(std::get<3>(t)); zInputsDeque.pop_front(); MergeToAddressWitnessAnchorData wad = jsopWitnessAnchorMap[jso.ToString()]; @@ -590,7 +594,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() // If this is the final output, set the target and memo if (isToZaddr_ && vpubNewProcessed) { outputType = "target"; - jso.addr = toPaymentAddress_; + jso.addr = boost::get(toPaymentAddress_); if (!hexMemo.empty()) { jso.memo = get_memo_from_hex_string(hexMemo); } @@ -852,7 +856,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( // placeholder for txid will be filled in later when tx has been finalized and signed. PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index}; JSOutput output = outputs[mapped_index]; - libzcash::PaymentAddress zaddr = output.addr; // randomized output + libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.h b/src/wallet/asyncrpcoperation_mergetoaddress.h index e6c8207e5..541a9541a 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.h +++ b/src/wallet/asyncrpcoperation_mergetoaddress.h @@ -37,7 +37,7 @@ struct MergeToAddressJSInfo { std::vector vjsin; std::vector vjsout; std::vector notes; - std::vector zkeys; + std::vector zkeys; CAmount vpub_old = 0; CAmount vpub_new = 0; }; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index e7aad3760..1df7bcd93 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -81,11 +81,13 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( if (!isfromtaddr_) { auto address = DecodePaymentAddress(fromAddress); - if (address) { - PaymentAddress addr = *address; + if (IsValidPaymentAddress(address)) { + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&address) != nullptr); + SproutPaymentAddress addr = boost::get(address); // We don't need to lock on the wallet as spending key related methods are thread-safe - SpendingKey key; + SproutSpendingKey key; if (!pwalletMain->GetSpendingKey(addr, key)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, no spending key found for zaddr"); } @@ -401,6 +403,9 @@ bool AsyncRPCOperation_sendmany::main_impl() { } std::deque zOutputsDeque; for (auto o : z_outputs_) { + // TODO: Add Sapling support. For now, ensure we can later convert freely. + auto addr = DecodePaymentAddress(std::get<0>(o)); + assert(boost::get(&addr) != nullptr); zOutputsDeque.push_back(o); } @@ -468,8 +473,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { std::string hexMemo = std::get<2>(smr); zOutputsDeque.pop_front(); - PaymentAddress pa = *DecodePaymentAddress(address); - JSOutput jso = JSOutput(pa, value); + PaymentAddress pa = DecodePaymentAddress(address); + JSOutput jso = JSOutput(boost::get(pa), value); if (hexMemo.size() > 0) { jso.memo = get_memo_from_hex_string(hexMemo); } @@ -569,7 +574,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { intermediates.insert(std::make_pair(tree.root(), tree)); // chained js are interstitial (found in between block boundaries) // Decrypt the change note's ciphertext to retrieve some data we need - ZCNoteDecryption decryptor(spendingkey_.receiving_key()); + ZCNoteDecryption decryptor(boost::get(spendingkey_).receiving_key()); auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey); try { SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt( @@ -579,7 +584,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { hSig, (unsigned char) changeOutputIndex); - SproutNote note = plaintext.note(frompaymentaddress_); + SproutNote note = plaintext.note(boost::get(frompaymentaddress_)); info.notes.push_back(note); jsInputValue += plaintext.value(); @@ -727,8 +732,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { assert(value==0); info.vjsout.push_back(JSOutput()); // dummy output while we accumulate funds into a change note for vpub_new } else { - PaymentAddress pa = *DecodePaymentAddress(address); - JSOutput jso = JSOutput(pa, value); + PaymentAddress pa = DecodePaymentAddress(address); + JSOutput jso = JSOutput(boost::get(pa), value); if (hexMemo.size() > 0) { jso.memo = get_memo_from_hex_string(hexMemo); } @@ -737,7 +742,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { // create output for any change if (jsChange>0) { - info.vjsout.push_back(JSOutput(frompaymentaddress_, jsChange)); + info.vjsout.push_back(JSOutput(boost::get(frompaymentaddress_), jsChange)); LogPrint("zrpcunsafe", "%s: generating note for change (amount=%s)\n", getId(), @@ -886,7 +891,7 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() { } for (CSproutNotePlaintextEntry & entry : entries) { - z_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.plaintext.note(frompaymentaddress_), CAmount(entry.plaintext.value()))); + z_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.plaintext.note(boost::get(frompaymentaddress_)), CAmount(entry.plaintext.value()))); std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); LogPrint("zrpcunsafe", "%s: found unspent note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n", getId(), @@ -948,7 +953,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit( if (!witnesses[i]) { throw runtime_error("joinsplit input could not be found in tree"); } - info.vjsin.push_back(JSInput(*witnesses[i], info.notes[i], spendingkey_)); + info.vjsin.push_back(JSInput(*witnesses[i], info.notes[i], boost::get(spendingkey_))); } // Make sure there are two inputs and two outputs @@ -1077,7 +1082,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit( // placeholder for txid will be filled in later when tx has been finalized and signed. PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index}; JSOutput output = outputs[mapped_index]; - libzcash::PaymentAddress zaddr = output.addr; // randomized output + libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 9546a4491..2cb5a7499 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -73,8 +73,10 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase( // Check the destination address is valid for this network i.e. not testnet being used on mainnet auto address = DecodePaymentAddress(toAddress); - if (address) { - tozaddr_ = *address; + if (IsValidPaymentAddress(address)) { + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&address) != nullptr); + tozaddr_ = address; } else { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid to address"); } @@ -233,7 +235,7 @@ bool AsyncRPCOperation_shieldcoinbase::main_impl() { ShieldCoinbaseJSInfo info; info.vpub_old = sendAmount; info.vpub_new = 0; - JSOutput jso = JSOutput(tozaddr_, sendAmount); + JSOutput jso = JSOutput(boost::get(tozaddr_), sendAmount); info.vjsout.push_back(jso); obj = perform_joinsplit(info); @@ -448,7 +450,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf // placeholder for txid will be filled in later when tx has been finalized and signed. PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index}; JSOutput output = outputs[mapped_index]; - libzcash::PaymentAddress zaddr = output.addr; // randomized output + libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 69a2649b1..57ce0c428 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -136,8 +136,8 @@ static bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector& vchCryptedSecret, - const libzcash::PaymentAddress& address, - libzcash::SpendingKey& sk) + const libzcash::SproutPaymentAddress& address, + libzcash::SproutSpendingKey& sk) { CKeyingMaterial vchSecret; if(!DecryptSecret(vMasterKey, vchCryptedSecret, address.GetHash(), vchSecret)) @@ -203,9 +203,9 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) CryptedSpendingKeyMap::const_iterator skmi = mapCryptedSpendingKeys.begin(); for (; skmi != mapCryptedSpendingKeys.end(); ++skmi) { - const libzcash::PaymentAddress &address = (*skmi).first; + const libzcash::SproutPaymentAddress &address = (*skmi).first; const std::vector &vchCryptedSecret = (*skmi).second; - libzcash::SpendingKey sk; + libzcash::SproutSpendingKey sk; if (!DecryptSpendingKey(vMasterKeyIn, vchCryptedSecret, address, sk)) { keyFail = true; @@ -298,7 +298,7 @@ bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) co return false; } -bool CCryptoKeyStore::AddSpendingKey(const libzcash::SpendingKey &sk) +bool CCryptoKeyStore::AddSpendingKey(const libzcash::SproutSpendingKey &sk) { { LOCK(cs_SpendingKeyStore); @@ -322,7 +322,7 @@ bool CCryptoKeyStore::AddSpendingKey(const libzcash::SpendingKey &sk) return true; } -bool CCryptoKeyStore::AddCryptedSpendingKey(const libzcash::PaymentAddress &address, +bool CCryptoKeyStore::AddCryptedSpendingKey(const libzcash::SproutPaymentAddress &address, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret) { @@ -337,7 +337,7 @@ bool CCryptoKeyStore::AddCryptedSpendingKey(const libzcash::PaymentAddress &addr return true; } -bool CCryptoKeyStore::GetSpendingKey(const libzcash::PaymentAddress &address, libzcash::SpendingKey &skOut) const +bool CCryptoKeyStore::GetSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey &skOut) const { { LOCK(cs_SpendingKeyStore); @@ -376,11 +376,11 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) mapKeys.clear(); BOOST_FOREACH(SpendingKeyMap::value_type& mSpendingKey, mapSpendingKeys) { - const libzcash::SpendingKey &sk = mSpendingKey.second; + const libzcash::SproutSpendingKey &sk = mSpendingKey.second; CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << sk; CKeyingMaterial vchSecret(ss.begin(), ss.end()); - libzcash::PaymentAddress address = sk.address(); + libzcash::SproutPaymentAddress address = sk.address(); std::vector vchCryptedSecret; if (!EncryptSecret(vMasterKeyIn, vchSecret, address.GetHash(), vchCryptedSecret)) return false; diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index e0d91ee5a..e42f5868a 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -200,11 +200,11 @@ public: mi++; } } - virtual bool AddCryptedSpendingKey(const libzcash::PaymentAddress &address, + virtual bool AddCryptedSpendingKey(const libzcash::SproutPaymentAddress &address, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret); - bool AddSpendingKey(const libzcash::SpendingKey &sk); - bool HaveSpendingKey(const libzcash::PaymentAddress &address) const + bool AddSpendingKey(const libzcash::SproutSpendingKey &sk); + bool HaveSpendingKey(const libzcash::SproutPaymentAddress &address) const { { LOCK(cs_SpendingKeyStore); @@ -214,8 +214,8 @@ public: } return false; } - bool GetSpendingKey(const libzcash::PaymentAddress &address, libzcash::SpendingKey &skOut) const; - void GetPaymentAddresses(std::set &setAddress) const + bool GetSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey &skOut) const; + void GetPaymentAddresses(std::set &setAddress) const { if (!IsCrypted()) { diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index ceea292d8..b2987cc17 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -68,22 +68,22 @@ public: } }; -CWalletTx GetValidReceive(const libzcash::SpendingKey& sk, CAmount value, bool randomInputs) { +CWalletTx GetValidReceive(const libzcash::SproutSpendingKey& sk, CAmount value, bool randomInputs) { return GetValidReceive(*params, sk, value, randomInputs); } -libzcash::SproutNote GetNote(const libzcash::SpendingKey& sk, +libzcash::SproutNote GetNote(const libzcash::SproutSpendingKey& sk, const CTransaction& tx, size_t js, size_t n) { return GetNote(*params, sk, tx, js, n); } -CWalletTx GetValidSpend(const libzcash::SpendingKey& sk, +CWalletTx GetValidSpend(const libzcash::SproutSpendingKey& sk, const libzcash::SproutNote& note, CAmount value) { return GetValidSpend(*params, sk, note, value); } JSOutPoint CreateValidBlock(TestWallet& wallet, - const libzcash::SpendingKey& sk, + const libzcash::SproutSpendingKey& sk, const CBlockIndex& index, CBlock& block, ZCIncrementalMerkleTree& tree) { @@ -112,7 +112,7 @@ TEST(wallet_tests, setup_datadir_location_run_as_first_test) { } TEST(wallet_tests, note_data_serialisation) { - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto wtx = GetValidReceive(sk, 10, true); auto note = GetNote(sk, wtx, 0, 1); auto nullifier = note.nullifier(sk); @@ -138,7 +138,7 @@ TEST(wallet_tests, note_data_serialisation) { TEST(wallet_tests, find_unspent_notes) { SelectParams(CBaseChainParams::TESTNET); CWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -295,7 +295,7 @@ TEST(wallet_tests, find_unspent_notes) { TEST(wallet_tests, set_note_addrs_in_cwallettx) { - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto wtx = GetValidReceive(sk, 10, true); auto note = GetNote(sk, wtx, 0, 1); auto nullifier = note.nullifier(sk); @@ -315,7 +315,7 @@ TEST(wallet_tests, set_invalid_note_addrs_in_cwallettx) { EXPECT_EQ(0, wtx.mapNoteData.size()); mapNoteData_t noteData; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; CNoteData nd {sk.address(), uint256()}; noteData[jsoutpt] = nd; @@ -326,7 +326,7 @@ TEST(wallet_tests, set_invalid_note_addrs_in_cwallettx) { TEST(wallet_tests, GetNoteNullifier) { CWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto address = sk.address(); auto dec = ZCNoteDecryption(sk.receiving_key()); @@ -357,8 +357,8 @@ TEST(wallet_tests, GetNoteNullifier) { TEST(wallet_tests, FindMyNotes) { CWallet wallet; - auto sk = libzcash::SpendingKey::random(); - auto sk2 = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); + auto sk2 = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk2); auto wtx = GetValidReceive(sk, 10, true); @@ -384,7 +384,7 @@ TEST(wallet_tests, FindMyNotesInEncryptedWallet) { uint256 r {GetRandHash()}; CKeyingMaterial vMasterKey (r.begin(), r.end()); - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); ASSERT_TRUE(wallet.EncryptKeys(vMasterKey)); @@ -412,7 +412,7 @@ TEST(wallet_tests, FindMyNotesInEncryptedWallet) { TEST(wallet_tests, get_conflicted_notes) { CWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -443,7 +443,7 @@ TEST(wallet_tests, get_conflicted_notes) { TEST(wallet_tests, nullifier_is_spent) { CWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -483,7 +483,7 @@ TEST(wallet_tests, nullifier_is_spent) { TEST(wallet_tests, navigate_from_nullifier_to_note) { CWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -509,7 +509,7 @@ TEST(wallet_tests, navigate_from_nullifier_to_note) { TEST(wallet_tests, spent_note_is_from_me) { CWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -537,7 +537,7 @@ TEST(wallet_tests, spent_note_is_from_me) { TEST(wallet_tests, cached_witnesses_empty_chain) { TestWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -590,7 +590,7 @@ TEST(wallet_tests, cached_witnesses_chain_tip) { CBlock block1; ZCIncrementalMerkleTree tree; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); { @@ -672,7 +672,7 @@ TEST(wallet_tests, CachedWitnessesDecrementFirst) { CBlockIndex index2(block2); ZCIncrementalMerkleTree tree; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); { @@ -744,7 +744,7 @@ TEST(wallet_tests, CachedWitnessesCleanIndex) { ZCIncrementalMerkleTree riTree = tree; std::vector> witnesses; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); // Generate a chain @@ -813,7 +813,7 @@ TEST(wallet_tests, CachedWitnessesCleanIndex) { TEST(wallet_tests, ClearNoteWitnessCache) { TestWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -862,7 +862,7 @@ TEST(wallet_tests, WriteWitnessCache) { MockWalletDB walletdb; CBlockLocator loc; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -939,7 +939,7 @@ TEST(wallet_tests, UpdateNullifierNoteMap) { uint256 r {GetRandHash()}; CKeyingMaterial vMasterKey (r.begin(), r.end()); - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); ASSERT_TRUE(wallet.EncryptKeys(vMasterKey)); @@ -972,7 +972,7 @@ TEST(wallet_tests, UpdateNullifierNoteMap) { TEST(wallet_tests, UpdatedNoteData) { TestWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -1019,7 +1019,7 @@ TEST(wallet_tests, UpdatedNoteData) { TEST(wallet_tests, MarkAffectedTransactionsDirty) { TestWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); @@ -1050,7 +1050,7 @@ TEST(wallet_tests, MarkAffectedTransactionsDirty) { TEST(wallet_tests, NoteLocking) { TestWallet wallet; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); auto wtx = GetValidReceive(sk, 10, true); diff --git a/src/wallet/gtest/test_wallet_zkeys.cpp b/src/wallet/gtest/test_wallet_zkeys.cpp index 474656474..efc06b962 100644 --- a/src/wallet/gtest/test_wallet_zkeys.cpp +++ b/src/wallet/gtest/test_wallet_zkeys.cpp @@ -20,12 +20,14 @@ TEST(wallet_zkeys_tests, store_and_load_zkeys) { CWallet wallet; // wallet should be empty - std::set addrs; + std::set addrs; wallet.GetPaymentAddresses(addrs); ASSERT_EQ(0, addrs.size()); // wallet should have one key - auto addr = wallet.GenerateNewZKey(); + auto address = wallet.GenerateNewZKey(); + ASSERT_NE(boost::get(&address), nullptr); + auto addr = boost::get(address); wallet.GetPaymentAddresses(addrs); ASSERT_EQ(1, addrs.size()); @@ -33,7 +35,7 @@ TEST(wallet_zkeys_tests, store_and_load_zkeys) { ASSERT_TRUE(wallet.HaveSpendingKey(addr)); // manually add new spending key to wallet - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); ASSERT_TRUE(wallet.AddZKey(sk)); // verify wallet did add it @@ -41,7 +43,7 @@ TEST(wallet_zkeys_tests, store_and_load_zkeys) { ASSERT_TRUE(wallet.HaveSpendingKey(addr)); // verify spending key stored correctly - libzcash::SpendingKey keyOut; + libzcash::SproutSpendingKey keyOut; wallet.GetSpendingKey(addr, keyOut); ASSERT_EQ(sk, keyOut); @@ -51,7 +53,7 @@ TEST(wallet_zkeys_tests, store_and_load_zkeys) { ASSERT_EQ(1, addrs.count(addr)); // Load a third key into the wallet - sk = libzcash::SpendingKey::random(); + sk = libzcash::SproutSpendingKey::random(); ASSERT_TRUE(wallet.LoadZKey(sk)); // attach metadata to this third key @@ -77,12 +79,12 @@ TEST(wallet_zkeys_tests, StoreAndLoadViewingKeys) { CWallet wallet; // wallet should be empty - std::set addrs; + std::set addrs; wallet.GetPaymentAddresses(addrs); ASSERT_EQ(0, addrs.size()); // manually add new viewing key to wallet - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto vk = sk.viewing_key(); ASSERT_TRUE(wallet.AddViewingKey(vk)); @@ -93,12 +95,12 @@ TEST(wallet_zkeys_tests, StoreAndLoadViewingKeys) { ASSERT_FALSE(wallet.HaveSpendingKey(addr)); // verify viewing key stored correctly - libzcash::ViewingKey vkOut; + libzcash::SproutViewingKey vkOut; wallet.GetViewingKey(addr, vkOut); ASSERT_EQ(vk, vkOut); // Load a second viewing key into the wallet - auto sk2 = libzcash::SpendingKey::random(); + auto sk2 = libzcash::SproutSpendingKey::random(); ASSERT_TRUE(wallet.LoadViewingKey(sk2.viewing_key())); // verify wallet did add it @@ -133,7 +135,7 @@ TEST(wallet_zkeys_tests, write_zkey_direct_to_db) { ASSERT_TRUE(fFirstRun); // wallet should be empty - std::set addrs; + std::set addrs; wallet.GetPaymentAddresses(addrs); ASSERT_EQ(0, addrs.size()); @@ -145,7 +147,7 @@ TEST(wallet_zkeys_tests, write_zkey_direct_to_db) { ASSERT_EQ(1, addrs.size()); // create random key and add it to database directly, bypassing wallet - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto addr = sk.address(); int64_t now = GetTime(); CKeyMetadata meta(now); @@ -171,7 +173,7 @@ TEST(wallet_zkeys_tests, write_zkey_direct_to_db) { ASSERT_TRUE(wallet.HaveSpendingKey(addr)); // check key is the same - libzcash::SpendingKey keyOut; + libzcash::SproutSpendingKey keyOut; wallet.GetSpendingKey(addr, keyOut); ASSERT_EQ(sk, keyOut); @@ -205,7 +207,7 @@ TEST(wallet_zkeys_tests, WriteViewingKeyDirectToDB) { ASSERT_TRUE(fFirstRun); // create random viewing key and add it to database directly, bypassing wallet - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto vk = sk.viewing_key(); auto addr = sk.address(); int64_t now = GetTime(); @@ -223,7 +225,7 @@ TEST(wallet_zkeys_tests, WriteViewingKeyDirectToDB) { ASSERT_TRUE(wallet.HaveViewingKey(addr)); // check key is the same - libzcash::ViewingKey vkOut; + libzcash::SproutViewingKey vkOut; wallet.GetViewingKey(addr, vkOut); ASSERT_EQ(vk, vkOut); } @@ -252,12 +254,14 @@ TEST(wallet_zkeys_tests, write_cryptedzkey_direct_to_db) { ASSERT_TRUE(fFirstRun); // wallet should be empty - std::set addrs; + std::set addrs; wallet.GetPaymentAddresses(addrs); ASSERT_EQ(0, addrs.size()); // Add random key to the wallet - auto paymentAddress = wallet.GenerateNewZKey(); + auto address = wallet.GenerateNewZKey(); + ASSERT_NE(boost::get(&address), nullptr); + auto paymentAddress = boost::get(address); // wallet should have one key wallet.GetPaymentAddresses(addrs); @@ -274,7 +278,9 @@ TEST(wallet_zkeys_tests, write_cryptedzkey_direct_to_db) { // unlock wallet and then add wallet.Unlock(strWalletPass); - auto paymentAddress2 = wallet.GenerateNewZKey(); + auto address2 = wallet.GenerateNewZKey(); + ASSERT_NE(boost::get(&address2), nullptr); + auto paymentAddress2 = boost::get(address2); // Create a new wallet from the existing wallet path CWallet wallet2("wallet_crypted.dat"); @@ -292,7 +298,7 @@ TEST(wallet_zkeys_tests, write_cryptedzkey_direct_to_db) { ASSERT_TRUE(addrs.count(paymentAddress2)); // spending key is crypted, so we can't extract valid payment address - libzcash::SpendingKey keyOut; + libzcash::SproutSpendingKey keyOut; wallet2.GetSpendingKey(paymentAddress, keyOut); ASSERT_FALSE(paymentAddress == keyOut.address()); diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index cfc8262b0..42e447160 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -253,7 +253,7 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp) } // Check the payment address is valid - PaymentAddress zaddr = pd.payload.zaddr; + SproutPaymentAddress zaddr = pd.payload.zaddr; { o.push_back(Pair("paymentAddress", EncodePaymentAddress(zaddr))); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 0a91c92eb..c84c41e46 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -296,9 +296,11 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys // Let's see if the address is a valid Zcash spending key if (fImportZKeys) { auto spendingkey = DecodeSpendingKey(vstr[0]); - if (spendingkey) { - libzcash::SpendingKey key = *spendingkey; - libzcash::PaymentAddress addr = key.address(); + if (IsValidSpendingKey(spendingkey)) { + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&spendingkey) != nullptr); + auto key = boost::get(spendingkey); + auto addr = key.address(); if (pwalletMain->HaveSpendingKey(addr)) { LogPrint("zrpc", "Skipping import of zaddr %s (key already present)\n", EncodePaymentAddress(addr)); continue; @@ -526,13 +528,13 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys) file << "\n"; if (fDumpZKeys) { - std::set addresses; + std::set addresses; pwalletMain->GetPaymentAddresses(addresses); file << "\n"; file << "# Zkeys\n"; file << "\n"; for (auto addr : addresses ) { - libzcash::SpendingKey key; + libzcash::SproutSpendingKey key; if (pwalletMain->GetSpendingKey(addr, key)) { std::string strTime = EncodeDumpTime(pwalletMain->mapZKeyMetadata[addr].nCreateTime); file << strprintf("%s %s # zaddr=%s\n", EncodeSpendingKey(key), strTime, EncodePaymentAddress(addr)); @@ -614,10 +616,12 @@ UniValue z_importkey(const UniValue& params, bool fHelp) string strSecret = params[0].get_str(); auto spendingkey = DecodeSpendingKey(strSecret); - if (!spendingkey) { + if (!IsValidSpendingKey(spendingkey)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key"); } - auto key = *spendingkey; + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&spendingkey) != nullptr); + auto key = boost::get(spendingkey); auto addr = key.address(); { @@ -706,10 +710,12 @@ UniValue z_importviewingkey(const UniValue& params, bool fHelp) string strVKey = params[0].get_str(); auto viewingkey = DecodeViewingKey(strVKey); - if (!viewingkey) { + if (!IsValidViewingKey(viewingkey)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid viewing key"); } - auto vkey = *viewingkey; + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&viewingkey) != nullptr); + auto vkey = boost::get(viewingkey); auto addr = vkey.address(); { @@ -766,12 +772,14 @@ UniValue z_exportkey(const UniValue& params, bool fHelp) string strAddress = params[0].get_str(); auto address = DecodePaymentAddress(strAddress); - if (!address) { + if (!IsValidPaymentAddress(address)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr"); } - auto addr = *address; + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&address) != nullptr); + auto addr = boost::get(address); - libzcash::SpendingKey k; + libzcash::SproutSpendingKey k; if (!pwalletMain->GetSpendingKey(addr, k)) throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private zkey for this zaddr"); @@ -804,14 +812,16 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp) string strAddress = params[0].get_str(); auto address = DecodePaymentAddress(strAddress); - if (!address) { + if (!IsValidPaymentAddress(address)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr"); } - auto addr = *address; + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&address) != nullptr); + auto addr = boost::get(address); - libzcash::ViewingKey vk; + libzcash::SproutViewingKey vk; if (!pwalletMain->GetViewingKey(addr, vk)) { - libzcash::SpendingKey k; + libzcash::SproutSpendingKey k; if (!pwalletMain->GetSpendingKey(addr, k)) { throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private key or viewing key for this zaddr"); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e39693069..e372c1cf4 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2522,8 +2522,10 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) } string address = o.get_str(); auto zaddr = DecodePaymentAddress(address); - if (zaddr) { - libzcash::PaymentAddress addr = *zaddr; + if (IsValidPaymentAddress(zaddr)) { + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&zaddr) != nullptr); + libzcash::SproutPaymentAddress addr = boost::get(zaddr); if (!fIncludeWatchonly && !pwalletMain->HaveSpendingKey(addr)) { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, spending key for address does not belong to wallet: ") + address); } @@ -2540,7 +2542,10 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) } else { // User did not provide zaddrs, so use default i.e. all addresses - pwalletMain->GetPaymentAddresses(zaddrs); + // TODO: Add Sapling support + std::set sproutzaddrs = {}; + pwalletMain->GetPaymentAddresses(sproutzaddrs); + zaddrs.insert(sproutzaddrs.begin(), sproutzaddrs.end()); } UniValue results(UniValue::VARR); @@ -2554,7 +2559,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) obj.push_back(Pair("jsindex", (int)entry.jsop.js )); obj.push_back(Pair("jsoutindex", (int)entry.jsop.n)); obj.push_back(Pair("confirmations", entry.nHeight)); - obj.push_back(Pair("spendable", pwalletMain->HaveSpendingKey(entry.address))); + obj.push_back(Pair("spendable", pwalletMain->HaveSpendingKey(boost::get(entry.address)))); obj.push_back(Pair("address", EncodePaymentAddress(entry.address))); obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value())))); std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); @@ -2793,10 +2798,13 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp) LOCK(cs_main); auto spendingkey = DecodeSpendingKey(params[0].get_str()); - if (!spendingkey) { + if (!IsValidSpendingKey(spendingkey)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key"); } - SpendingKey k = *spendingkey; + if (boost::get(&spendingkey) == nullptr) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys"); + } + SproutSpendingKey k = boost::get(spendingkey); uint256 epk; unsigned char nonce; @@ -2826,7 +2834,7 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp) h_sig, nonce ); - PaymentAddress payment_addr = k.address(); + SproutPaymentAddress payment_addr = k.address(); SproutNote decrypted_note = npt.note(payment_addr); assert(pwalletMain != NULL); @@ -2902,15 +2910,18 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp) std::vector vjsin; std::vector vjsout; std::vector notes; - std::vector keys; + std::vector keys; std::vector commitments; for (const string& name_ : inputs.getKeys()) { auto spendingkey = DecodeSpendingKey(inputs[name_].get_str()); - if (!spendingkey) { + if (!IsValidSpendingKey(spendingkey)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key"); } - SpendingKey k = *spendingkey; + if (boost::get(&spendingkey) == nullptr) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys"); + } + SproutSpendingKey k = boost::get(spendingkey); keys.push_back(k); @@ -2921,7 +2932,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp) ssData >> npt; } - PaymentAddress addr = k.address(); + SproutPaymentAddress addr = k.address(); SproutNote note = npt.note(addr); notes.push_back(note); commitments.push_back(note.cm()); @@ -2952,12 +2963,15 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp) for (const string& name_ : outputs.getKeys()) { auto addrTo = DecodePaymentAddress(name_); - if (!addrTo) { + if (!IsValidPaymentAddress(addrTo)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address."); } + if (boost::get(&addrTo) == nullptr) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout payment addresses"); + } CAmount nAmount = AmountFromValue(outputs[name_]); - vjsout.push_back(JSOutput(*addrTo, nAmount)); + vjsout.push_back(JSOutput(boost::get(addrTo), nAmount)); } while (vjsout.size() < ZC_NUM_JS_OUTPUTS) { @@ -3063,7 +3077,7 @@ UniValue zc_raw_keygen(const UniValue& params, bool fHelp) ); } - auto k = SpendingKey::random(); + auto k = SproutSpendingKey::random(); auto addr = k.address(); auto viewing_key = k.viewing_key(); @@ -3130,7 +3144,8 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp) } UniValue ret(UniValue::VARR); - std::set addresses; + // TODO: Add Sapling support + std::set addresses; pwalletMain->GetPaymentAddresses(addresses); for (auto addr : addresses ) { if (fIncludeWatchonly || pwalletMain->HaveSpendingKey(addr)) { @@ -3232,11 +3247,14 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) auto fromaddress = params[0].get_str(); auto zaddr = DecodePaymentAddress(fromaddress); - if (!zaddr) { + if (!IsValidPaymentAddress(zaddr)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr."); } + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&zaddr) != nullptr); + auto sproutzaddr = boost::get(zaddr); - if (!(pwalletMain->HaveSpendingKey(*zaddr) || pwalletMain->HaveViewingKey(*zaddr))) { + if (!(pwalletMain->HaveSpendingKey(sproutzaddr) || pwalletMain->HaveViewingKey(sproutzaddr))) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found."); } @@ -3299,13 +3317,14 @@ UniValue z_getbalance(const UniValue& params, bool fHelp) bool fromTaddr = false; CTxDestination taddr = DecodeDestination(fromaddress); fromTaddr = IsValidDestination(taddr); - libzcash::PaymentAddress zaddr; if (!fromTaddr) { auto res = DecodePaymentAddress(fromaddress); - if (!res) { + if (!IsValidPaymentAddress(res)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr."); } - zaddr = *res; + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&res) != nullptr); + auto zaddr = boost::get(res); if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found."); } @@ -3534,14 +3553,16 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) bool fromTaddr = false; CTxDestination taddr = DecodeDestination(fromaddress); fromTaddr = IsValidDestination(taddr); - libzcash::PaymentAddress zaddr; + libzcash::SproutPaymentAddress zaddr; if (!fromTaddr) { auto res = DecodePaymentAddress(fromaddress); - if (!res) { + if (!IsValidPaymentAddress(res)) { // invalid throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr."); } - zaddr = *res; + // TODO: Add Sapling support. For now, ensure we can freely convert. + assert(boost::get(&res) != nullptr); + zaddr = boost::get(res); } // Check that we have the spending key @@ -3579,7 +3600,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) bool isZaddr = false; CTxDestination taddr = DecodeDestination(address); if (!IsValidDestination(taddr)) { - if (DecodePaymentAddress(address)) { + if (IsValidPaymentAddressString(address)) { isZaddr = true; } else { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address ); @@ -3773,7 +3794,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) // Validate the destination address auto destaddress = params[1].get_str(); - if (!DecodePaymentAddress(destaddress)) { + if (!IsValidPaymentAddressString(destaddress)) { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress ); } @@ -4015,10 +4036,10 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) } } else { auto zaddr = DecodePaymentAddress(address); - if (zaddr) { + if (IsValidPaymentAddress(zaddr)) { // Ignore listed z-addrs if we are using all of them if (!(useAny || useAnyNote)) { - zaddrs.insert(*zaddr); + zaddrs.insert(zaddr); } } else { throw JSONRPCError( @@ -4038,7 +4059,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) bool isToZaddr = false; CTxDestination taddr = DecodeDestination(destaddress); if (!IsValidDestination(taddr)) { - if (DecodePaymentAddress(destaddress)) { + if (IsValidPaymentAddressString(destaddress)) { isToZaddr = true; } else { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress ); @@ -4174,9 +4195,11 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp) maxedOutNotesFlag = true; } else { estimatedTxSize += increase; - SpendingKey zkey; - pwalletMain->GetSpendingKey(entry.address, zkey); - noteInputs.emplace_back(entry.jsop, entry.plaintext.note(entry.address), nValue, zkey); + // TODO: Add Sapling support + auto zaddr = boost::get(entry.address); + SproutSpendingKey zkey; + pwalletMain->GetSpendingKey(zaddr, zkey); + noteInputs.emplace_back(entry.jsop, entry.plaintext.note(zaddr), nValue, zkey); mergedNoteValue += nValue; } } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index eb9093235..27f96af58 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -83,7 +83,8 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const libzcash::PaymentAddress CWallet::GenerateNewZKey() { AssertLockHeld(cs_wallet); // mapZKeyMetadata - auto k = SpendingKey::random(); + // TODO: Add Sapling support + auto k = SproutSpendingKey::random(); auto addr = k.address(); // Check for collision, even though it is unlikely to ever occur @@ -100,7 +101,8 @@ libzcash::PaymentAddress CWallet::GenerateNewZKey() } // Add spending key to keystore and persist to disk -bool CWallet::AddZKey(const libzcash::SpendingKey &key) +// TODO: Add Sapling support +bool CWallet::AddZKey(const libzcash::SproutSpendingKey &key) { AssertLockHeld(cs_wallet); // mapZKeyMetadata auto addr = key.address(); @@ -194,7 +196,7 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, } -bool CWallet::AddCryptedSpendingKey(const libzcash::PaymentAddress &address, +bool CWallet::AddCryptedSpendingKey(const libzcash::SproutPaymentAddress &address, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret) { @@ -229,7 +231,7 @@ bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta) return true; } -bool CWallet::LoadZKeyMetadata(const PaymentAddress &addr, const CKeyMetadata &meta) +bool CWallet::LoadZKeyMetadata(const SproutPaymentAddress &addr, const CKeyMetadata &meta) { AssertLockHeld(cs_wallet); // mapZKeyMetadata mapZKeyMetadata[addr] = meta; @@ -241,17 +243,17 @@ bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) +bool CWallet::LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedSpendingKey(addr, rk, vchCryptedSecret); } -bool CWallet::LoadZKey(const libzcash::SpendingKey &key) +bool CWallet::LoadZKey(const libzcash::SproutSpendingKey &key) { return CCryptoKeyStore::AddSpendingKey(key); } -bool CWallet::AddViewingKey(const libzcash::ViewingKey &vk) +bool CWallet::AddViewingKey(const libzcash::SproutViewingKey &vk) { if (!CCryptoKeyStore::AddViewingKey(vk)) { return false; @@ -263,7 +265,7 @@ bool CWallet::AddViewingKey(const libzcash::ViewingKey &vk) return CWalletDB(strWalletFile).WriteViewingKey(vk); } -bool CWallet::RemoveViewingKey(const libzcash::ViewingKey &vk) +bool CWallet::RemoveViewingKey(const libzcash::SproutViewingKey &vk) { AssertLockHeld(cs_wallet); if (!CCryptoKeyStore::RemoveViewingKey(vk)) { @@ -278,7 +280,7 @@ bool CWallet::RemoveViewingKey(const libzcash::ViewingKey &vk) return true; } -bool CWallet::LoadViewingKey(const libzcash::ViewingKey &vk) +bool CWallet::LoadViewingKey(const libzcash::SproutViewingKey &vk) { return CCryptoKeyStore::AddViewingKey(vk); } @@ -1257,7 +1259,7 @@ void CWallet::EraseFromWallet(const uint256 &hash) * Throws std::runtime_error if the decryptor doesn't match this note */ boost::optional CWallet::GetNoteNullifier(const JSDescription& jsdesc, - const libzcash::PaymentAddress& address, + const libzcash::SproutPaymentAddress& address, const ZCNoteDecryption& dec, const uint256& hSig, uint8_t n) const @@ -1273,7 +1275,7 @@ boost::optional CWallet::GetNoteNullifier(const JSDescription& jsdesc, // SpendingKeys are only available if: // - We have them (this isn't a viewing key) // - The wallet is unlocked - libzcash::SpendingKey key; + libzcash::SproutSpendingKey key; if (GetSpendingKey(address, key)) { ret = note.nullifier(key); } @@ -3715,7 +3717,7 @@ void CWallet::GetFilteredNotes(std::vector & outEntri std::set filterAddresses; if (address.length() > 0) { - filterAddresses.insert(*DecodePaymentAddress(address)); + filterAddresses.insert(DecodePaymentAddress(address)); } GetFilteredNotes(outEntries, filterAddresses, minDepth, ignoreSpent, ignoreUnspendable); @@ -3749,7 +3751,7 @@ void CWallet::GetFilteredNotes( for (auto & pair : wtx.mapNoteData) { JSOutPoint jsop = pair.first; CNoteData nd = pair.second; - PaymentAddress pa = nd.address; + SproutPaymentAddress pa = nd.address; // skip notes which belong to a different payment address in the wallet if (!(filterAddresses.empty() || filterAddresses.count(pa))) { @@ -3830,7 +3832,7 @@ void CWallet::GetUnspentFilteredNotes( for (auto & pair : wtx.mapNoteData) { JSOutPoint jsop = pair.first; CNoteData nd = pair.second; - PaymentAddress pa = nd.address; + SproutPaymentAddress pa = nd.address; // skip notes which belong to a different payment address in the wallet if (!(filterAddresses.empty() || filterAddresses.count(pa))) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index a9b8bc7e1..df99a001f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -199,7 +199,7 @@ public: class CNoteData { public: - libzcash::PaymentAddress address; + libzcash::SproutPaymentAddress address; /** * Cached note nullifier. May not be set if the wallet was not unlocked when @@ -233,9 +233,9 @@ public: int witnessHeight; CNoteData() : address(), nullifier(), witnessHeight {-1} { } - CNoteData(libzcash::PaymentAddress a) : + CNoteData(libzcash::SproutPaymentAddress a) : address {a}, nullifier(), witnessHeight {-1} { } - CNoteData(libzcash::PaymentAddress a, uint256 n) : + CNoteData(libzcash::SproutPaymentAddress a, uint256 n) : address {a}, nullifier {n}, witnessHeight {-1} { } ADD_SERIALIZE_METHODS; @@ -268,14 +268,14 @@ typedef std::map mapNoteData_t; struct CSproutNotePlaintextEntry { JSOutPoint jsop; - libzcash::PaymentAddress address; + libzcash::SproutPaymentAddress address; libzcash::SproutNotePlaintext plaintext; }; /** Decrypted note, location in a transaction, and confirmation height. */ struct CUnspentSproutNotePlaintextEntry { JSOutPoint jsop; - libzcash::PaymentAddress address; + libzcash::SproutPaymentAddress address; libzcash::SproutNotePlaintext plaintext; int nHeight; }; @@ -785,7 +785,7 @@ public: std::set setKeyPool; std::map mapKeyMetadata; - std::map mapZKeyMetadata; + std::map mapZKeyMetadata; typedef std::map MasterKeyMap; MasterKeyMap mapMasterKeys; @@ -962,21 +962,21 @@ public: //! Generates a new zaddr libzcash::PaymentAddress GenerateNewZKey(); //! Adds spending key to the store, and saves it to disk - bool AddZKey(const libzcash::SpendingKey &key); + bool AddZKey(const libzcash::SproutSpendingKey &key); //! Adds spending key to the store, without saving it to disk (used by LoadWallet) - bool LoadZKey(const libzcash::SpendingKey &key); + bool LoadZKey(const libzcash::SproutSpendingKey &key); //! Load spending key metadata (used by LoadWallet) - bool LoadZKeyMetadata(const libzcash::PaymentAddress &addr, const CKeyMetadata &meta); + bool LoadZKeyMetadata(const libzcash::SproutPaymentAddress &addr, const CKeyMetadata &meta); //! Adds an encrypted spending key to the store, without saving it to disk (used by LoadWallet) - bool LoadCryptedZKey(const libzcash::PaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret); + bool LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret); //! Adds an encrypted spending key to the store, and saves it to disk (virtual method, declared in crypter.h) - bool AddCryptedSpendingKey(const libzcash::PaymentAddress &address, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret); + bool AddCryptedSpendingKey(const libzcash::SproutPaymentAddress &address, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret); //! Adds a viewing key to the store, and saves it to disk. - bool AddViewingKey(const libzcash::ViewingKey &vk); - bool RemoveViewingKey(const libzcash::ViewingKey &vk); + bool AddViewingKey(const libzcash::SproutViewingKey &vk); + bool RemoveViewingKey(const libzcash::SproutViewingKey &vk); //! Adds a viewing key to the store, without saving it to disk (used by LoadWallet) - bool LoadViewingKey(const libzcash::ViewingKey &dest); + bool LoadViewingKey(const libzcash::SproutViewingKey &dest); /** * Increment the next transaction order id @@ -1039,7 +1039,7 @@ public: boost::optional GetNoteNullifier( const JSDescription& jsdesc, - const libzcash::PaymentAddress& address, + const libzcash::SproutPaymentAddress& address, const ZCNoteDecryption& dec, const uint256& hSig, uint8_t n) const; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 7bb222651..568843f74 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -105,7 +105,7 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, return true; } -bool CWalletDB::WriteCryptedZKey(const libzcash::PaymentAddress & addr, +bool CWalletDB::WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr, const libzcash::ReceivingKey &rk, const std::vector& vchCryptedSecret, const CKeyMetadata &keyMeta) @@ -131,7 +131,7 @@ bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true); } -bool CWalletDB::WriteZKey(const libzcash::PaymentAddress& addr, const libzcash::SpendingKey& key, const CKeyMetadata &keyMeta) +bool CWalletDB::WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta) { nWalletDBUpdated++; @@ -142,13 +142,13 @@ bool CWalletDB::WriteZKey(const libzcash::PaymentAddress& addr, const libzcash:: return Write(std::make_pair(std::string("zkey"), addr), key, false); } -bool CWalletDB::WriteViewingKey(const libzcash::ViewingKey &vk) +bool CWalletDB::WriteViewingKey(const libzcash::SproutViewingKey &vk) { nWalletDBUpdated++; return Write(std::make_pair(std::string("vkey"), vk), '1'); } -bool CWalletDB::EraseViewingKey(const libzcash::ViewingKey &vk) +bool CWalletDB::EraseViewingKey(const libzcash::SproutViewingKey &vk) { nWalletDBUpdated++; return Erase(std::make_pair(std::string("vkey"), vk)); @@ -485,7 +485,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "vkey") { - libzcash::ViewingKey vk; + libzcash::SproutViewingKey vk; ssKey >> vk; char fYes; ssValue >> fYes; @@ -498,9 +498,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "zkey") { - libzcash::PaymentAddress addr; + libzcash::SproutPaymentAddress addr; ssKey >> addr; - libzcash::SpendingKey key; + libzcash::SproutSpendingKey key; ssValue >> key; if (!pwallet->LoadZKey(key)) @@ -607,7 +607,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "czkey") { - libzcash::PaymentAddress addr; + libzcash::SproutPaymentAddress addr; ssKey >> addr; // Deserialization of a pair is just one item after another uint256 rkValue; @@ -641,7 +641,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "zkeymeta") { - libzcash::PaymentAddress addr; + libzcash::SproutPaymentAddress addr; ssKey >> addr; CKeyMetadata keyMeta; ssValue >> keyMeta; diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index c388921f0..318993a65 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -133,14 +133,14 @@ public: static bool Recover(CDBEnv& dbenv, const std::string& filename); /// Write spending key to wallet database, where key is payment address and value is spending key. - bool WriteZKey(const libzcash::PaymentAddress& addr, const libzcash::SpendingKey& key, const CKeyMetadata &keyMeta); - bool WriteCryptedZKey(const libzcash::PaymentAddress & addr, + bool WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta); + bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr, const libzcash::ReceivingKey & rk, const std::vector& vchCryptedSecret, const CKeyMetadata &keyMeta); - bool WriteViewingKey(const libzcash::ViewingKey &vk); - bool EraseViewingKey(const libzcash::ViewingKey &vk); + bool WriteViewingKey(const libzcash::SproutViewingKey &vk); + bool EraseViewingKey(const libzcash::SproutViewingKey &vk); private: CWalletDB(const CWalletDB&); diff --git a/src/zcash/Address.cpp b/src/zcash/Address.cpp index baefeae4e..270119512 100644 --- a/src/zcash/Address.cpp +++ b/src/zcash/Address.cpp @@ -6,7 +6,7 @@ namespace libzcash { -uint256 PaymentAddress::GetHash() const { +uint256 SproutPaymentAddress::GetHash() const { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << *this; return Hash(ss.begin(), ss.end()); @@ -16,24 +16,37 @@ uint256 ReceivingKey::pk_enc() const { return ZCNoteEncryption::generate_pubkey(*this); } -PaymentAddress ViewingKey::address() const { - return PaymentAddress(a_pk, sk_enc.pk_enc()); +SproutPaymentAddress SproutViewingKey::address() const { + return SproutPaymentAddress(a_pk, sk_enc.pk_enc()); } -ReceivingKey SpendingKey::receiving_key() const { +ReceivingKey SproutSpendingKey::receiving_key() const { return ReceivingKey(ZCNoteEncryption::generate_privkey(*this)); } -ViewingKey SpendingKey::viewing_key() const { - return ViewingKey(PRF_addr_a_pk(*this), receiving_key()); +SproutViewingKey SproutSpendingKey::viewing_key() const { + return SproutViewingKey(PRF_addr_a_pk(*this), receiving_key()); } -SpendingKey SpendingKey::random() { - return SpendingKey(random_uint252()); +SproutSpendingKey SproutSpendingKey::random() { + return SproutSpendingKey(random_uint252()); } -PaymentAddress SpendingKey::address() const { +SproutPaymentAddress SproutSpendingKey::address() const { return viewing_key().address(); } } + + +bool IsValidPaymentAddress(const libzcash::PaymentAddress& zaddr) { + return zaddr.which() != 0; +} + +bool IsValidViewingKey(const libzcash::ViewingKey& vk) { + return vk.which() != 0; +} + +bool IsValidSpendingKey(const libzcash::SpendingKey& zkey) { + return zkey.which() != 0; +} diff --git a/src/zcash/Address.hpp b/src/zcash/Address.hpp index c165c20dd..1fba11d9d 100644 --- a/src/zcash/Address.hpp +++ b/src/zcash/Address.hpp @@ -5,19 +5,26 @@ #include "uint252.h" #include "serialize.h" +#include + namespace libzcash { +class InvalidEncoding { +public: + friend bool operator==(const InvalidEncoding &a, const InvalidEncoding &b) { return true; } + friend bool operator<(const InvalidEncoding &a, const InvalidEncoding &b) { return true; } +}; const size_t SerializedPaymentAddressSize = 64; const size_t SerializedViewingKeySize = 64; const size_t SerializedSpendingKeySize = 32; -class PaymentAddress { +class SproutPaymentAddress { public: uint256 a_pk; uint256 pk_enc; - PaymentAddress() : a_pk(), pk_enc() { } - PaymentAddress(uint256 a_pk, uint256 pk_enc) : a_pk(a_pk), pk_enc(pk_enc) { } + SproutPaymentAddress() : a_pk(), pk_enc() { } + SproutPaymentAddress(uint256 a_pk, uint256 pk_enc) : a_pk(a_pk), pk_enc(pk_enc) { } ADD_SERIALIZE_METHODS; @@ -30,10 +37,10 @@ public: //! Get the 256-bit SHA256d hash of this payment address. uint256 GetHash() const; - friend inline bool operator==(const PaymentAddress& a, const PaymentAddress& b) { + friend inline bool operator==(const SproutPaymentAddress& a, const SproutPaymentAddress& b) { return a.a_pk == b.a_pk && a.pk_enc == b.pk_enc; } - friend inline bool operator<(const PaymentAddress& a, const PaymentAddress& b) { + friend inline bool operator<(const SproutPaymentAddress& a, const SproutPaymentAddress& b) { return (a.a_pk < b.a_pk || (a.a_pk == b.a_pk && a.pk_enc < b.pk_enc)); } @@ -47,13 +54,13 @@ public: uint256 pk_enc() const; }; -class ViewingKey { +class SproutViewingKey { public: uint256 a_pk; ReceivingKey sk_enc; - ViewingKey() : a_pk(), sk_enc() { } - ViewingKey(uint256 a_pk, ReceivingKey sk_enc) : a_pk(a_pk), sk_enc(sk_enc) { } + SproutViewingKey() : a_pk(), sk_enc() { } + SproutViewingKey(uint256 a_pk, ReceivingKey sk_enc) : a_pk(a_pk), sk_enc(sk_enc) { } ADD_SERIALIZE_METHODS; @@ -63,29 +70,42 @@ public: READWRITE(sk_enc); } - PaymentAddress address() const; + SproutPaymentAddress address() const; - friend inline bool operator==(const ViewingKey& a, const ViewingKey& b) { + friend inline bool operator==(const SproutViewingKey& a, const SproutViewingKey& b) { return a.a_pk == b.a_pk && a.sk_enc == b.sk_enc; } - friend inline bool operator<(const ViewingKey& a, const ViewingKey& b) { + friend inline bool operator<(const SproutViewingKey& a, const SproutViewingKey& b) { return (a.a_pk < b.a_pk || (a.a_pk == b.a_pk && a.sk_enc < b.sk_enc)); } }; -class SpendingKey : public uint252 { +class SproutSpendingKey : public uint252 { public: - SpendingKey() : uint252() { } - SpendingKey(uint252 a_sk) : uint252(a_sk) { } + SproutSpendingKey() : uint252() { } + SproutSpendingKey(uint252 a_sk) : uint252(a_sk) { } - static SpendingKey random(); + static SproutSpendingKey random(); ReceivingKey receiving_key() const; - ViewingKey viewing_key() const; - PaymentAddress address() const; + SproutViewingKey viewing_key() const; + SproutPaymentAddress address() const; }; +typedef boost::variant PaymentAddress; +typedef boost::variant ViewingKey; +typedef boost::variant SpendingKey; + } +/** Check whether a PaymentAddress is not an InvalidEncoding. */ +bool IsValidPaymentAddress(const libzcash::PaymentAddress& zaddr); + +/** Check whether a ViewingKey is not an InvalidEncoding. */ +bool IsValidViewingKey(const libzcash::ViewingKey& vk); + +/** Check whether a SpendingKey is not an InvalidEncoding. */ +bool IsValidSpendingKey(const libzcash::SpendingKey& zkey); + #endif // ZC_ADDRESS_H_ diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index 1dd0da0b4..a503cb455 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -370,12 +370,12 @@ SproutNote JSOutput::note(const uint252& phi, const uint256& r, size_t i, const } JSOutput::JSOutput() : addr(uint256(), uint256()), value(0) { - SpendingKey a_sk = SpendingKey::random(); + SproutSpendingKey a_sk = SproutSpendingKey::random(); addr = a_sk.address(); } JSInput::JSInput() : witness(ZCIncrementalMerkleTree().witness()), - key(SpendingKey::random()) { + key(SproutSpendingKey::random()) { note = SproutNote(key.address().a_pk, 0, random_uint256(), random_uint256()); ZCIncrementalMerkleTree dummy_tree; dummy_tree.append(note.cm()); diff --git a/src/zcash/JoinSplit.hpp b/src/zcash/JoinSplit.hpp index 28ca98e97..03c499ff0 100644 --- a/src/zcash/JoinSplit.hpp +++ b/src/zcash/JoinSplit.hpp @@ -19,12 +19,12 @@ class JSInput { public: ZCIncrementalWitness witness; SproutNote note; - SpendingKey key; + SproutSpendingKey key; JSInput(); JSInput(ZCIncrementalWitness witness, SproutNote note, - SpendingKey key) : witness(witness), note(note), key(key) { } + SproutSpendingKey key) : witness(witness), note(note), key(key) { } uint256 nullifier() const { return note.nullifier(key); @@ -33,12 +33,12 @@ public: class JSOutput { public: - PaymentAddress addr; + SproutPaymentAddress addr; uint64_t value; boost::array memo = {{0xF6}}; // 0xF6 is invalid UTF8 as per spec, rest of array is 0x00 JSOutput(); - JSOutput(PaymentAddress addr, uint64_t value) : addr(addr), value(value) { } + JSOutput(SproutPaymentAddress addr, uint64_t value) : addr(addr), value(value) { } SproutNote note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const; }; diff --git a/src/zcash/Note.cpp b/src/zcash/Note.cpp index 407925e15..3315a7c45 100644 --- a/src/zcash/Note.cpp +++ b/src/zcash/Note.cpp @@ -34,7 +34,7 @@ uint256 SproutNote::cm() const { return result; } -uint256 SproutNote::nullifier(const SpendingKey& a_sk) const { +uint256 SproutNote::nullifier(const SproutSpendingKey& a_sk) const { return PRF_nf(a_sk, rho); } @@ -46,7 +46,7 @@ SproutNotePlaintext::SproutNotePlaintext( r = note.r; } -SproutNote SproutNotePlaintext::note(const PaymentAddress& addr) const +SproutNote SproutNotePlaintext::note(const SproutPaymentAddress& addr) const { return SproutNote(addr.a_pk, value_, rho, r); } diff --git a/src/zcash/Note.hpp b/src/zcash/Note.hpp index 7c7f0c561..ac785fe1b 100644 --- a/src/zcash/Note.hpp +++ b/src/zcash/Note.hpp @@ -35,7 +35,7 @@ public: virtual uint256 cm() const override; - uint256 nullifier(const SpendingKey& a_sk) const; + uint256 nullifier(const SproutSpendingKey& a_sk) const; }; class BaseNotePlaintext { @@ -61,7 +61,7 @@ public: SproutNotePlaintext(const SproutNote& note, boost::array memo); - SproutNote note(const PaymentAddress& addr) const; + SproutNote note(const SproutPaymentAddress& addr) const; virtual ~SproutNotePlaintext() {} diff --git a/src/zcash/circuit/note.tcc b/src/zcash/circuit/note.tcc index d1534ec4b..c598c62ee 100644 --- a/src/zcash/circuit/note.tcc +++ b/src/zcash/circuit/note.tcc @@ -118,7 +118,7 @@ public: void generate_r1cs_witness( const MerklePath& path, - const SpendingKey& key, + const SproutSpendingKey& key, const SproutNote& note ) { note_gadget::generate_r1cs_witness(note); diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 80c726b5a..9a794089c 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -281,11 +281,11 @@ double benchmark_try_decrypt_notes(size_t nAddrs) { CWallet wallet; for (int i = 0; i < nAddrs; i++) { - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); } - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); auto tx = GetValidReceive(*pzcashParams, sk, 10, true); struct timeval tv_start; @@ -299,7 +299,7 @@ double benchmark_increment_note_witnesses(size_t nTxs) CWallet wallet; ZCIncrementalMerkleTree tree; - auto sk = libzcash::SpendingKey::random(); + auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); // First block