Load previously persisted sent transaction recipient metadata back into the wallet.

This completes some unfinished work from #5549
This commit is contained in:
Steven Smith 2022-03-16 23:53:46 -07:00 committed by Kris Nuttycombe
parent cf84e1e79d
commit 9993d948ef
4 changed files with 76 additions and 2 deletions

View File

@ -853,6 +853,66 @@ bool CWallet::LoadUnifiedAddressMetadata(const ZcashdUnifiedAddressMetadata &add
addrmeta.GetReceiverTypes());
}
PaymentAddress CWallet::GetPaymentAddressForRecipient(const uint256& txid, const libzcash::RecipientAddress recipient) const {
// TODO: We should scrub change addresses from the results here.
auto defaultAddress = [&]() -> PaymentAddress {
return std::visit(match {
[&](const CKeyID& addr) {
auto ua = pwalletMain->FindUnifiedAddressByReceiver(addr);
if (ua.has_value()) {
return libzcash::PaymentAddress{ua.value()};
} else {
return libzcash::PaymentAddress{addr};
}
},
[&](const CScriptID& addr) {
auto ua = pwalletMain->FindUnifiedAddressByReceiver(addr);
if (ua.has_value()) {
return libzcash::PaymentAddress{ua.value()};
} else {
return libzcash::PaymentAddress{addr};
}
},
[&](const SaplingPaymentAddress& addr) {
auto ua = pwalletMain->FindUnifiedAddressByReceiver(addr);
if (ua.has_value()) {
return libzcash::PaymentAddress{ua.value()};
} else {
return libzcash::PaymentAddress{addr};
}
},
[&](const OrchardRawAddress& addr) {
auto ua = pwalletMain->FindUnifiedAddressByReceiver(addr);
if (ua.has_value()) {
return libzcash::PaymentAddress{ua.value()};
} else {
return libzcash::PaymentAddress{UnifiedAddress::ForSingleReceiver(addr)};
}
}
}, recipient);
};
auto recipientsPtr = sendRecipients.find(txid);
if (recipientsPtr == sendRecipients.end()) {
// we don't know the recipient, so we just return the simplest type
return defaultAddress();
} else {
// search the list of recipient mappings for one corresponding to
// our recipient, and return the known UA if it exists; otherwise
// just use the default.
for (const auto& mapping : recipientsPtr->second) {
if (mapping.address == recipient && mapping.ua.has_value()) {
return PaymentAddress{mapping.ua.value()};
}
}
return defaultAddress();
}
}
void CWallet::LoadRecipientMapping(const uint256& txid, const RecipientMapping& mapping) {
sendRecipients[txid].push_back(mapping);
}
bool CWallet::LoadCaches()
{
AssertLockHeld(cs_wallet);

View File

@ -1262,6 +1262,8 @@ public:
std::map<uint256, CWalletTx> mapWallet;
std::map<uint256, std::vector<RecipientMapping>> sendRecipients;
typedef std::multimap<int64_t, CWalletTx*> TxItems;
TxItems wtxOrdered;
@ -1578,6 +1580,9 @@ public:
bool LoadUnifiedAccountMetadata(const ZcashdUnifiedAccountMetadata &skmeta);
bool LoadUnifiedAddressMetadata(const ZcashdUnifiedAddressMetadata &addrmeta);
libzcash::PaymentAddress GetPaymentAddressForRecipient(const uint256& txid, const libzcash::RecipientAddress recipient) const;
void LoadRecipientMapping(const uint256& txid, const RecipientMapping& mapping);
//! Reconstructs (in memory) caches and mappings for unified accounts,
//! addresses and keying material. This should be called once, after the
//! remainder of the on-disk wallet data has been loaded.
@ -1665,12 +1670,13 @@ public:
for (const auto& recipient : recipients)
{
sendRecipients[txid].push_back(recipient);
if (recipient.ua.has_value()) {
CWalletDB(strWalletFile).WriteRecipientMapping(
assert(CWalletDB(strWalletFile).WriteRecipientMapping(
txid,
recipient.address,
recipient.ua.value()
);
));
}
}

View File

@ -892,6 +892,8 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
strErr = "Error in wallet database: recipientmapping UA does not contain recipient";
return false;
}
pwallet->LoadRecipientMapping(txid, RecipientMapping(ua.value(), recipient));
}
else if (strType == "orchard_note_commitment_tree")
{

View File

@ -67,6 +67,12 @@ class UnifiedAddress {
public:
UnifiedAddress() {}
static UnifiedAddress ForSingleReceiver(Receiver receiver) {
UnifiedAddress ua;
ua.AddReceiver(receiver);
return ua;
}
static std::optional<UnifiedAddress> Parse(const KeyConstants& keyConstants, const std::string& str);
ADD_SERIALIZE_METHODS;