Use legacy address for Sapling migration until UA functionality is available to the RPC tests.
This commit is contained in:
parent
ebab190fdf
commit
d8d9cd129e
|
@ -191,8 +191,9 @@ CAmount AsyncRPCOperation_saplingmigration::chooseAmount(const CAmount& availabl
|
|||
return amount;
|
||||
}
|
||||
|
||||
// Unless otherwise specified, the migration destination address is the address for Sapling account 0
|
||||
// at the smallest diversifier index that produces a valid diversified address.
|
||||
// Unless otherwise specified, the migration destination address is the address
|
||||
// the legacy Sapling account (0x7FFFFFFE) at the smallest diversifier index
|
||||
// that produces a valid diversified address.
|
||||
libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigrationDestAddress(const HDSeed& seed) {
|
||||
KeyIO keyIO(Params());
|
||||
if (mapArgs.count("-migrationdestaddress")) {
|
||||
|
@ -203,17 +204,9 @@ libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigration
|
|||
return *saplingAddress;
|
||||
}
|
||||
|
||||
auto usk = pwalletMain->GetUnifiedSpendingKeyForAccount(0);
|
||||
assert(usk.has_value()); // mnemonic seeds are currently always generated to have valid USKs at account 0
|
||||
auto ua = usk.value().ToFullViewingKey().FindAddress(libzcash::diversifier_index_t(0));
|
||||
auto addr = ua.first.GetSaplingPaymentAddress();
|
||||
if (addr.has_value()) {
|
||||
return addr.value();
|
||||
} else {
|
||||
// This error will only occur if Sapling address generation has been disbled for USKs from this
|
||||
// wallet.
|
||||
throw std::runtime_error(std::string(__func__) + ": No Sapling address generated for account 0.");
|
||||
}
|
||||
// TODO: move off of legacy addresses.
|
||||
auto generatedKey = pwalletMain->GenerateLegacySaplingZKey(0);
|
||||
return generatedKey.first.ToXFVK().DefaultAddress();
|
||||
}
|
||||
|
||||
void AsyncRPCOperation_saplingmigration::cancel() {
|
||||
|
|
|
@ -29,8 +29,7 @@ TEST(WalletZkeysTest, StoreAndLoadSaplingZkeys) {
|
|||
ASSERT_EQ(0, addrs.size());
|
||||
|
||||
// No HD seed in the wallet
|
||||
auto legacyKey = wallet.GenerateNewLegacySaplingZKey();
|
||||
ASSERT_FALSE(legacyKey.has_value());
|
||||
EXPECT_ANY_THROW(wallet.GenerateNewLegacySaplingZKey());
|
||||
|
||||
// Load the all-zeroes seed
|
||||
std::string mnemonic("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art");
|
||||
|
@ -41,9 +40,7 @@ TEST(WalletZkeysTest, StoreAndLoadSaplingZkeys) {
|
|||
wallet.LoadMnemonicSeed(seed);
|
||||
|
||||
// Now this call succeeds
|
||||
legacyKey = wallet.GenerateNewLegacySaplingZKey();
|
||||
ASSERT_TRUE(legacyKey.has_value());
|
||||
auto address = legacyKey.value();
|
||||
auto address = wallet.GenerateNewLegacySaplingZKey();
|
||||
|
||||
// wallet should have one key
|
||||
wallet.GetSaplingPaymentAddresses(addrs);
|
||||
|
@ -433,12 +430,13 @@ TEST(WalletZkeysTest, WriteCryptedSaplingZkeyDirectToDb) {
|
|||
// No default CPubKey set
|
||||
ASSERT_TRUE(fFirstRun);
|
||||
|
||||
ASSERT_FALSE(wallet.HaveLegacyHDSeed());
|
||||
ASSERT_FALSE(wallet.HaveMnemonicSeed());
|
||||
|
||||
// Load the all-zeroes seed as the legacy seed
|
||||
std::string mnemonic("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art");
|
||||
MnemonicSeed seed(English, mnemonic);
|
||||
wallet.LoadMnemonicSeed(seed);
|
||||
ASSERT_TRUE(wallet.HaveMnemonicSeed());
|
||||
|
||||
// wallet should be empty
|
||||
std::set<libzcash::SaplingPaymentAddress> addrs;
|
||||
|
@ -446,7 +444,7 @@ TEST(WalletZkeysTest, WriteCryptedSaplingZkeyDirectToDb) {
|
|||
ASSERT_EQ(0, addrs.size());
|
||||
|
||||
// Add random key to the wallet
|
||||
auto address = wallet.GenerateNewLegacySaplingZKey().value();
|
||||
auto address = wallet.GenerateNewLegacySaplingZKey();
|
||||
|
||||
// wallet should have one key
|
||||
wallet.GetSaplingPaymentAddresses(addrs);
|
||||
|
@ -470,13 +468,11 @@ TEST(WalletZkeysTest, WriteCryptedSaplingZkeyDirectToDb) {
|
|||
ASSERT_TRUE(wallet.EncryptWallet(strWalletPass));
|
||||
|
||||
// adding a new key will fail as the wallet is locked
|
||||
EXPECT_FALSE(wallet.GenerateNewLegacySaplingZKey().has_value());
|
||||
EXPECT_ANY_THROW(wallet.GenerateNewLegacySaplingZKey());
|
||||
|
||||
// unlock wallet and then add
|
||||
wallet.Unlock(strWalletPass);
|
||||
auto address2Opt = wallet.GenerateNewLegacySaplingZKey();
|
||||
EXPECT_TRUE(address2Opt.has_value());
|
||||
auto address2 = address2Opt.value();
|
||||
auto address2 = wallet.GenerateNewLegacySaplingZKey();
|
||||
|
||||
// flush the wallet to prevent race conditions
|
||||
wallet.Flush();
|
||||
|
|
|
@ -2941,11 +2941,7 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp)
|
|||
return keyIO.EncodePaymentAddress(pwalletMain->GenerateNewSproutZKey());
|
||||
} else if (addrType == ADDR_TYPE_SAPLING) {
|
||||
auto saplingAddress = pwalletMain->GenerateNewLegacySaplingZKey();
|
||||
if (saplingAddress.has_value()) {
|
||||
return keyIO.EncodePaymentAddress(saplingAddress.value());
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "No legacy HD seed available; please use z_getunifiedaddress instead.");
|
||||
}
|
||||
return keyIO.EncodePaymentAddress(saplingAddress);
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid address type");
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ static UniValue ValueFromString(const std::string &str)
|
|||
}
|
||||
|
||||
static SaplingPaymentAddress DefaultSaplingAddress(CWallet* pwallet) {
|
||||
auto usk = pwallet->GetUnifiedSpendingKeyForAccount(0);
|
||||
auto usk = pwallet->GenerateUnifiedSpendingKeyForAccount(0);
|
||||
|
||||
return usk.value()
|
||||
.ToFullViewingKey()
|
||||
|
|
|
@ -118,48 +118,59 @@ libzcash::SproutPaymentAddress CWallet::GenerateNewSproutZKey()
|
|||
// is not present. When using legacy HD seeds, the account index is determined
|
||||
// by trial of legacyHDChain.GetAccountCounter(); for unified addresses this must use
|
||||
// valued derived from legacyHDChain.unifiedAccountCounter
|
||||
std::optional<SaplingPaymentAddress> CWallet::GenerateNewLegacySaplingZKey() {
|
||||
SaplingPaymentAddress CWallet::GenerateNewLegacySaplingZKey() {
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
auto seedOpt = GetMnemonicSeed();
|
||||
if (seedOpt.has_value()) {
|
||||
auto seed = seedOpt.value();
|
||||
if (!mnemonicHDChain.has_value()) {
|
||||
mnemonicHDChain = CHDChain(seed.Fingerprint(), GetTime());
|
||||
}
|
||||
CHDChain& hdChain = mnemonicHDChain.value();
|
||||
|
||||
// loop until we find an unused address index
|
||||
while (true) {
|
||||
auto xsk = libzcash::SaplingExtendedSpendingKey::Legacy(
|
||||
seed,
|
||||
BIP44CoinType(),
|
||||
hdChain.GetLegacySaplingKeyCounter());
|
||||
// advance the address index counter so that the next time we need to generate
|
||||
// a key we're pointing at a free index.
|
||||
hdChain.IncrementLegacySaplingKeyCounter();
|
||||
if (HaveSaplingSpendingKey(xsk.first.ToXFVK())) {
|
||||
// try the next index
|
||||
continue;
|
||||
} else {
|
||||
// Update the persisted chain information
|
||||
if (fFileBacked && !CWalletDB(strWalletFile).WriteMnemonicHDChain(hdChain)) {
|
||||
throw std::runtime_error("CWallet::GenerateNewLegacySaplingZKey(): Writing HD chain model failed");
|
||||
}
|
||||
|
||||
auto ivk = xsk.first.expsk.full_viewing_key().in_viewing_key();
|
||||
mapSaplingZKeyMetadata[ivk] = xsk.second;
|
||||
|
||||
if (!AddSaplingZKey(xsk.first)) {
|
||||
throw std::runtime_error("CWallet::GenerateNewLegacySaplingZKey(): AddSaplingZKey failed");
|
||||
}
|
||||
|
||||
return xsk.first.ToXFVK().DefaultAddress();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return std::nullopt;
|
||||
if (!mnemonicHDChain.has_value()) {
|
||||
mnemonicHDChain = CHDChain(GetMnemonicSeed().value().Fingerprint(), GetTime());
|
||||
}
|
||||
CHDChain& hdChain = mnemonicHDChain.value();
|
||||
|
||||
// loop until we find an unused address index
|
||||
while (true) {
|
||||
auto generatedKey = GenerateLegacySaplingZKey(hdChain.GetLegacySaplingKeyCounter());
|
||||
auto xfvk = generatedKey.first.ToXFVK();
|
||||
|
||||
// advance the address index counter so that the next time we need to generate
|
||||
// a key we're pointing at a free index.
|
||||
hdChain.IncrementLegacySaplingKeyCounter();
|
||||
if (!generatedKey.second) {
|
||||
// the key already existed, so try the next one
|
||||
continue;
|
||||
} else {
|
||||
// Update the persisted chain information
|
||||
if (fFileBacked && !CWalletDB(strWalletFile).WriteMnemonicHDChain(hdChain)) {
|
||||
throw std::runtime_error(
|
||||
"CWallet::GenerateLegacySaplingZKey(): Writing HD chain model failed");
|
||||
}
|
||||
|
||||
return xfvk.DefaultAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<SaplingExtendedSpendingKey, bool> CWallet::GenerateLegacySaplingZKey(uint32_t addrIndex) {
|
||||
auto seedOpt = GetMnemonicSeed();
|
||||
if (!seedOpt.has_value()) {
|
||||
throw std::runtime_error(
|
||||
"CWallet::GenerateLegacySaplingZKey(): Wallet does not have a mnemonic seed.");
|
||||
}
|
||||
|
||||
auto seed = seedOpt.value();
|
||||
|
||||
auto xsk = libzcash::SaplingExtendedSpendingKey::Legacy(seed, BIP44CoinType(), addrIndex);
|
||||
if (!HaveSaplingSpendingKey(xsk.first.ToXFVK())) {
|
||||
auto ivk = xsk.first.expsk.full_viewing_key().in_viewing_key();
|
||||
mapSaplingZKeyMetadata[ivk] = xsk.second;
|
||||
|
||||
if (!AddSaplingZKey(xsk.first)) {
|
||||
throw std::runtime_error("CWallet::GenerateLegacySaplingZKey(): AddSaplingZKey failed.");
|
||||
}
|
||||
return std::make_pair(xsk.first, true) ;
|
||||
} else {
|
||||
return std::make_pair(xsk.first, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add spending key to keystore
|
||||
|
@ -238,9 +249,7 @@ bool CWallet::AddSproutZKey(const libzcash::SproutSpendingKey &key)
|
|||
return true;
|
||||
|
||||
if (!IsCrypted()) {
|
||||
return CWalletDB(strWalletFile).WriteZKey(addr,
|
||||
key,
|
||||
mapSproutZKeyMetadata[addr]);
|
||||
return CWalletDB(strWalletFile).WriteZKey(addr, key, mapSproutZKeyMetadata[addr]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -394,35 +403,33 @@ bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullVi
|
|||
UnifiedSpendingKey CWallet::GenerateNewUnifiedSpendingKey() {
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
auto seed = GetMnemonicSeed();
|
||||
if (!seed.has_value()) {
|
||||
throw std::runtime_error(std::string(__func__) + ": Wallet has no mnemonic HD seed. Please upgrade this wallet.");
|
||||
}
|
||||
|
||||
CHDChain& hdChain = mnemonicHDChain.value();
|
||||
while (true) {
|
||||
auto usk = UnifiedSpendingKey::ForAccount(seed.value(), BIP44CoinType(), hdChain.GetAccountCounter());
|
||||
auto usk = GenerateUnifiedSpendingKeyForAccount(hdChain.GetAccountCounter());
|
||||
hdChain.IncrementAccountCounter();
|
||||
|
||||
if (usk.has_value()) {
|
||||
// Update the persisted chain information
|
||||
if (fFileBacked && !CWalletDB(strWalletFile).WriteMnemonicHDChain(hdChain)) {
|
||||
throw std::runtime_error("CWallet::GenerateNewUnifiedSpendingKey(): Writing HD chain model failed");
|
||||
throw std::runtime_error(
|
||||
"CWallet::GenerateNewUnifiedSpendingKey(): Writing HD chain model failed");
|
||||
}
|
||||
|
||||
// TODO: Save the unified full viewing key to the wallet metadata
|
||||
|
||||
return usk.value().first;
|
||||
return usk.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<libzcash::UnifiedSpendingKey> CWallet::GetUnifiedSpendingKeyForAccount(uint32_t accountId) {
|
||||
std::optional<libzcash::UnifiedSpendingKey> CWallet::GenerateUnifiedSpendingKeyForAccount(uint32_t accountId) {
|
||||
auto seed = GetMnemonicSeed();
|
||||
assert(seed.has_value());
|
||||
// TODO: is there any reason to cache and not re-derive this every time?
|
||||
if (!seed.has_value()) {
|
||||
throw std::runtime_error(std::string(__func__) + ": Wallet has no mnemonic HD seed. Please upgrade this wallet.");
|
||||
}
|
||||
|
||||
auto usk = UnifiedSpendingKey::ForAccount(seed.value(), BIP44CoinType(), accountId);
|
||||
if (usk.has_value()) {
|
||||
// TODO: Save the unified full viewing key & metadata to the wallet
|
||||
|
||||
return usk.value().first;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
|
|
|
@ -1058,10 +1058,14 @@ public:
|
|||
* Sapling ZKeys
|
||||
*/
|
||||
|
||||
//! Generates new Sapling key using the legacy HD seed (if one is available)
|
||||
//! and legacy account counter, stores the newly generated spending key to
|
||||
//! the wallet, and returns the default address for the newly generated key.
|
||||
std::optional<libzcash::SaplingPaymentAddress> GenerateNewLegacySaplingZKey();
|
||||
//! Generates new Sapling key, stores the newly generated spending
|
||||
//! key to the wallet, and returns the default address for the newly generated key.
|
||||
libzcash::SaplingPaymentAddress GenerateNewLegacySaplingZKey();
|
||||
//! Generates Sapling key at the specified address index, and stores the newly generated
|
||||
//! spending key to the wallet if it has not alreay been persisted.
|
||||
//! Returns the newly created key, its metadata, and a flag distinguishing
|
||||
//! whether or not the key was already known by the wallet.
|
||||
std::pair<libzcash::SaplingExtendedSpendingKey, bool> GenerateLegacySaplingZKey(uint32_t addrIndex);
|
||||
//! Adds Sapling spending key to the store, and saves it to disk
|
||||
bool AddSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key);
|
||||
//! Add Sapling full viewing key to the wallet.
|
||||
|
@ -1096,7 +1100,7 @@ public:
|
|||
* Unified keys & addresses
|
||||
*/
|
||||
libzcash::UnifiedSpendingKey GenerateNewUnifiedSpendingKey();
|
||||
std::optional<libzcash::UnifiedSpendingKey> GetUnifiedSpendingKeyForAccount(uint32_t accountId);
|
||||
std::optional<libzcash::UnifiedSpendingKey> GenerateUnifiedSpendingKeyForAccount(uint32_t accountId);
|
||||
|
||||
/**
|
||||
* Increment the next transaction order id
|
||||
|
|
Loading…
Reference in New Issue