From 2173767365e05acb1bb32b4f0cb664d786ea902d Mon Sep 17 00:00:00 2001 From: Jay Graber Date: Tue, 3 Jul 2018 14:51:27 -0700 Subject: [PATCH] Add crypted keystore sapling add key --- src/keystore.h | 3 ++ src/test/key_tests.cpp | 2 +- src/wallet/crypter.cpp | 44 ++++++++++++++++++++++++++ src/wallet/crypter.h | 8 ++++- src/wallet/gtest/test_wallet_zkeys.cpp | 23 ++++++++++++++ src/zcash/Address.cpp | 6 ++++ src/zcash/Address.hpp | 3 ++ 7 files changed, 87 insertions(+), 2 deletions(-) diff --git a/src/keystore.h b/src/keystore.h index 541c0bca5..76772dbf1 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -262,4 +262,7 @@ typedef std::vector > CKeyingMate typedef std::map > > CryptedKeyMap; typedef std::map > CryptedSpendingKeyMap; +//! Sapling +typedef std::map > CryptedSaplingSpendingKeyMap; + #endif // BITCOIN_KEYSTORE_H diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 03661f7b2..d864ca8be 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(zs_address_test) { auto addr = sk.default_address(); - std::string addr_string = EncodePaymentAddress(*addr); + std::string addr_string = EncodePaymentAddress(addr); BOOST_CHECK(addr_string.compare(0, 2, Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS)) == 0); auto paymentaddr2 = DecodePaymentAddress(addr_string); diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 57ce0c428..a1e6b42f6 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -322,6 +322,35 @@ bool CCryptoKeyStore::AddSpendingKey(const libzcash::SproutSpendingKey &sk) return true; } +bool CCryptoKeyStore::AddSaplingSpendingKey(const libzcash::SaplingSpendingKey &sk) +{ + { + LOCK(cs_SpendingKeyStore); + if (!IsCrypted()) { + return CBasicKeyStore::AddSaplingSpendingKey(sk); + } + + if (IsLocked()) { + return false; + } + + std::vector vchCryptedSecret; + CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << sk; + CKeyingMaterial vchSecret(ss.begin(), ss.end()); + auto address = sk.default_address(); + auto fvk = sk.full_viewing_key(); + if (!EncryptSecret(vMasterKey, vchSecret, address.GetHash(), vchCryptedSecret)) { + return false; + } + + if (!AddCryptedSaplingSpendingKey(fvk, vchCryptedSecret)) { + return false; + } + } + return true; +} + bool CCryptoKeyStore::AddCryptedSpendingKey(const libzcash::SproutPaymentAddress &address, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret) @@ -337,6 +366,21 @@ bool CCryptoKeyStore::AddCryptedSpendingKey(const libzcash::SproutPaymentAddress return true; } +// TODO: Handle note decryptors +bool CCryptoKeyStore::AddCryptedSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk, + const std::vector &vchCryptedSecret) +{ + { + LOCK(cs_SpendingKeyStore); + if (!SetCrypted()) { + return false; + } + + mapCryptedSaplingSpendingKeys[fvk] = vchCryptedSecret; + } + return true; +} + bool CCryptoKeyStore::GetSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey &skOut) const { { diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index e42f5868a..dba4c4c12 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -129,7 +129,9 @@ class CCryptoKeyStore : public CBasicKeyStore private: CryptedKeyMap mapCryptedKeys; CryptedSpendingKeyMap mapCryptedSpendingKeys; - + + CryptedSaplingSpendingKeyMap mapCryptedSaplingSpendingKeys; + CKeyingMaterial vMasterKey; //! if fUseCrypto is true, mapKeys and mapSpendingKeys must be empty @@ -230,6 +232,10 @@ public: mi++; } } + //! Sapling + virtual bool AddCryptedSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk, + const std::vector &vchCryptedSecret); + bool AddSaplingSpendingKey(const libzcash::SaplingSpendingKey &sk); /** * Wallet status (encrypted, locked) changed. diff --git a/src/wallet/gtest/test_wallet_zkeys.cpp b/src/wallet/gtest/test_wallet_zkeys.cpp index efc06b962..317e4ff54 100644 --- a/src/wallet/gtest/test_wallet_zkeys.cpp +++ b/src/wallet/gtest/test_wallet_zkeys.cpp @@ -7,6 +7,29 @@ #include +/** + * This test covers Sapling methods on CWallet + * GenerateNewSaplingZKey() + */ +TEST(wallet_zkeys_tests, store_and_load_sapling_zkeys) { + SelectParams(CBaseChainParams::MAIN); + + CWallet wallet; + + auto address = wallet.GenerateNewSaplingZKey(); + + // verify wallet has incoming viewing key for the address + ASSERT_TRUE(wallet.HaveSaplingIncomingViewingKey(address)); + + // manually add new spending key to wallet + auto sk = libzcash::SaplingSpendingKey::random(); + ASSERT_TRUE(wallet.AddSaplingZKey(sk)); + + // verify wallet did add it + auto fvk = sk.full_viewing_key(); + ASSERT_TRUE(wallet.HaveSaplingSpendingKey(fvk)); +} + /** * This test covers methods on CWallet * GenerateNewZKey() diff --git a/src/zcash/Address.cpp b/src/zcash/Address.cpp index e6dd0125a..a3db85a20 100644 --- a/src/zcash/Address.cpp +++ b/src/zcash/Address.cpp @@ -39,6 +39,12 @@ SproutPaymentAddress SproutSpendingKey::address() const { } //! Sapling +uint256 SaplingPaymentAddress::GetHash() const { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << *this; + return Hash(ss.begin(), ss.end()); +} + SaplingFullViewingKey SaplingExpandedSpendingKey::full_viewing_key() const { uint256 ak; uint256 nk; diff --git a/src/zcash/Address.hpp b/src/zcash/Address.hpp index 2a0d7a481..01eb14f54 100644 --- a/src/zcash/Address.hpp +++ b/src/zcash/Address.hpp @@ -111,6 +111,9 @@ public: READWRITE(d); READWRITE(pk_d); } + + //! Get the 256-bit SHA256d hash of this payment address. + uint256 GetHash() const; friend inline bool operator==(const SaplingPaymentAddress& a, const SaplingPaymentAddress& b) { return a.d == b.d && a.pk_d == b.pk_d;