From 225c78f3ab31d6e77457ca333fcb1f67182b11a9 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Fri, 18 Feb 2022 19:00:00 -0600 Subject: [PATCH] Add Orchard components to unified spending keys Co-authored-by: Jack Grigg --- src/gtest/test_keys.cpp | 28 ++++++++++++++++++++++++++++ src/wallet/wallet.cpp | 3 ++- src/zcash/address/unified.cpp | 5 ++++- src/zcash/address/unified.h | 8 +++++++- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/gtest/test_keys.cpp b/src/gtest/test_keys.cpp index d0578f990..6d68cdb57 100644 --- a/src/gtest/test_keys.cpp +++ b/src/gtest/test_keys.cpp @@ -195,6 +195,16 @@ TEST(Keys, DeriveUnifiedFullViewingKeys) if (test.size() == 1) continue; // comment try { + // [ + // t_key_bytes, + // sapling_fvk_bytes, + // orchard_fvk_bytes, + // unknown_fvk_typecode, + // unknown_fvk_bytes, + // unified_fvk, + // root_seed, + // account, + // ], auto seed_hex = test[6].get_str(); auto seed_data = ParseHex(seed_hex); RawHDSeed raw_seed(seed_data.begin(), seed_data.end()); @@ -244,6 +254,24 @@ TEST(Keys, DeriveUnifiedFullViewingKeys) auto key = libzcash::SaplingDiversifiableFullViewingKey::Read(ss); EXPECT_EQ(key, saplingKey); } + if (!test[2].isNull()) { + auto expectedHex = test[2].get_str(); + + // Ensure that the serialized Orchard fvk matches the test data. + auto orchardKey = ufvk.GetOrchardKey().value(); + CDataStream ssEncode(SER_NETWORK, PROTOCOL_VERSION); + ssEncode << orchardKey; + EXPECT_EQ(ssEncode.size(), 96); + auto skeyHex = HexStr(ssEncode.begin(), ssEncode.end()); + EXPECT_EQ(expectedHex, skeyHex); + + // Ensure that parsing the test data derives the correct dfvk + auto data = ParseHex(expectedHex); + ASSERT_EQ(data.size(), 96); + CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION); + auto key = libzcash::OrchardFullViewingKey::Read(ss); + EXPECT_EQ(key, orchardKey); + } // Enable the following after Orchard keys are supported. //{ // auto fvk_data = ParseHex(test[5].get_str()); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 474c0eae8..f57bd8ae0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -576,7 +576,8 @@ std::optional throw std::runtime_error("CWallet::GenerateUnifiedSpendingKeyForAccount(): Failed to add Sapling change address to the wallet."); }; - // TODO ORCHARD: Add Orchard component to the wallet + // Add Orchard spending key to the wallet + orchardWallet.AddSpendingKey(usk.value().GetOrchardKey()); auto zufvk = ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(Params(), ufvk); if (!CCryptoKeyStore::AddUnifiedFullViewingKey(zufvk)) { diff --git a/src/zcash/address/unified.cpp b/src/zcash/address/unified.cpp index ca9a8f9b6..93dd1b34f 100644 --- a/src/zcash/address/unified.cpp +++ b/src/zcash/address/unified.cpp @@ -39,7 +39,9 @@ std::optional ZcashdUnifiedSpendingKey::ForAccount( auto saplingKey = SaplingExtendedSpendingKey::ForAccount(seed, bip44CoinType, accountId); - return ZcashdUnifiedSpendingKey(transparentKey.value(), saplingKey.first); + auto orchardKey = OrchardSpendingKey::ForAccount(seed, bip44CoinType, accountId); + + return ZcashdUnifiedSpendingKey(transparentKey.value(), saplingKey.first, orchardKey); } UnifiedFullViewingKey ZcashdUnifiedSpendingKey::ToFullViewingKey() const { @@ -47,6 +49,7 @@ UnifiedFullViewingKey ZcashdUnifiedSpendingKey::ToFullViewingKey() const { builder.AddTransparentKey(transparentKey.ToAccountPubKey()); builder.AddSaplingKey(saplingKey.ToXFVK()); + builder.AddOrchardKey(orchardKey.ToFullViewingKey()); // This call to .value() is safe as ZcashdUnifiedSpendingKey values are always // constructed to contain all required components. diff --git a/src/zcash/address/unified.h b/src/zcash/address/unified.h index f388013bb..d76152239 100644 --- a/src/zcash/address/unified.h +++ b/src/zcash/address/unified.h @@ -248,10 +248,12 @@ class ZcashdUnifiedSpendingKey { private: transparent::AccountKey transparentKey; SaplingExtendedSpendingKey saplingKey; + OrchardSpendingKey orchardKey; ZcashdUnifiedSpendingKey( transparent::AccountKey tkey, - SaplingExtendedSpendingKey skey): transparentKey(tkey), saplingKey(skey) {} + SaplingExtendedSpendingKey skey, + OrchardSpendingKey okey): transparentKey(tkey), saplingKey(skey), orchardKey(okey) {} public: static std::optional ForAccount( const HDSeed& seed, @@ -266,6 +268,10 @@ public: return saplingKey; } + const OrchardSpendingKey& GetOrchardKey() const { + return orchardKey; + } + UnifiedFullViewingKey ToFullViewingKey() const; };