asyncnotedecryption #389

Open
duke wants to merge 14 commits from asyncnotedecryption into dev
  1. 4
      src/init.cpp
  2. 1
      src/main.cpp
  3. 3
      src/main.h
  4. 8
      src/wallet/rpchushwallet.cpp
  5. 8
      src/wallet/rpcwallet.cpp
  6. 187
      src/wallet/wallet.cpp
  7. 13
      src/wallet/wallet.h
  8. 4
      src/zcash/Note.cpp
  9. 6
      src/zcash/Note.hpp

4
src/init.cpp

@ -396,6 +396,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-prune=<n>", strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode disables wallet support and is incompatible with -txindex. "
"Warning: Reverting this setting requires re-downloading the entire blockchain. "
"(default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files)"), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
strUsage += HelpMessageOpt("-asyncnotedecryption", strprintf(_("Option to toggle parallel Sapling note trial decryption (default: %u)"), DEFAULT_ASYNC_NOTE_DECRYPTION));
strUsage += HelpMessageOpt("-reindex", _("Rebuild block chain index from current blk000??.dat files on startup"));
#if !defined(WIN32)
strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)"));
@ -1337,6 +1338,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
fPruneMode = true;
}
fAsyncNoteDecryption = GetBoolArg("-asyncnotedecryption", DEFAULT_ASYNC_NOTE_DECRYPTION);
LogPrintf("Asynchronous Sapling note trial decryption is %s\n", fAsyncNoteDecryption ? "enabled" : "disabled");
RegisterAllCoreRPCCommands(tableRPC);
#ifdef ENABLE_WALLET
bool fDisableWallet = GetBoolArg("-disablewallet", false);

1
src/main.cpp

@ -102,6 +102,7 @@ bool fIsBareMultisigStd = true;
bool fCheckBlockIndex = false;
bool fCheckpointsEnabled = true;
bool fCoinbaseEnforcedProtectionEnabled = true;
bool fAsyncNoteDecryption = DEFAULT_ASYNC_NOTE_DECRYPTION;
size_t nCoinCacheUsage = 5000 * 300;
uint64_t nPruneTarget = 0;
// If the tip is older than this (in seconds), the node is considered to be in initial block download.

3
src/main.h

@ -114,6 +114,8 @@ static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60;
/** Maximum length of reject messages. */
static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
/** Default for -asyncnotedecryption */
static const bool DEFAULT_ASYNC_NOTE_DECRYPTION = true;
// NSPV enabled?
static const bool DEFAULT_NSPV_PROCESSING = false;
@ -160,6 +162,7 @@ extern bool fZindex;
extern bool fIsBareMultisigStd;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;
extern bool fAsyncNoteDecryption;
// TODO: remove this flag by structuring our code such that
// it is unneeded for testing
extern bool fCoinbaseEnforcedProtectionEnabled;

8
src/wallet/rpchushwallet.cpp

@ -93,7 +93,7 @@ void zsTxSpendsToJSON(const CWalletTx& wtx, UniValue& spends, CAmount& totalSpen
const CWalletTx* parent = pwalletMain->GetWalletTx(pwalletMain->mapSaplingNullifiersToNotes[spendDesc.nullifier].hash);
const OutputDescription& output = parent->vShieldedOutput[op.n];
auto nd = pwalletMain->mapWallet[pwalletMain->mapSaplingNullifiersToNotes[spendDesc.nullifier].hash].mapSaplingNoteData[op];
auto pt = libzcash::SaplingNotePlaintext::decrypt(output.encCiphertext,nd.ivk,output.ephemeralKey,output.cm);
auto pt = libzcash::SaplingNotePlaintext::decrypt(Params().GetConsensus(), chainActive.Height(), output.encCiphertext,nd.ivk,output.ephemeralKey,output.cm);
if (pt) {
auto note = pt.get();
@ -197,7 +197,7 @@ void zsTxReceivedToJSON(const CWalletTx& wtx, UniValue& received, CAmount& total
for (auto addr : addresses) {
libzcash::SaplingExtendedSpendingKey extsk;
if (pwalletMain->GetSaplingExtendedSpendingKey(addr, extsk)) {
auto pt = libzcash::SaplingNotePlaintext::decrypt(
auto pt = libzcash::SaplingNotePlaintext::decrypt( Params().GetConsensus(), chainActive.Height(),
outputDesc.encCiphertext, extsk.expsk.full_viewing_key().in_viewing_key(), outputDesc.ephemeralKey, outputDesc.cm);
if (pt) {
@ -311,7 +311,7 @@ void zsTxSendsToJSON(const CWalletTx& wtx, UniValue& sends, CAmount& totalSends,
if (opt) {
auto opt_unwrapped = opt.get();
auto pt = libzcash::SaplingNotePlaintext::decrypt(
auto pt = libzcash::SaplingNotePlaintext::decrypt( Params().GetConsensus(), chainActive.Height(),
outputDesc.encCiphertext,outputDesc.ephemeralKey,opt_unwrapped.esk,opt_unwrapped.pk_d,outputDesc.cm);
if (pt) {
@ -342,7 +342,7 @@ void zsTxSendsToJSON(const CWalletTx& wtx, UniValue& sends, CAmount& totalSends,
if (opt) {
auto opt_unwrapped = opt.get();
auto pt = libzcash::SaplingNotePlaintext::decrypt(
auto pt = libzcash::SaplingNotePlaintext::decrypt( Params().GetConsensus(), chainActive.Height(),
outputDesc.encCiphertext,outputDesc.ephemeralKey,opt_unwrapped.esk,opt_unwrapped.pk_d,outputDesc.cm);
if (pt) {

8
src/wallet/rpcwallet.cpp

@ -3083,7 +3083,7 @@ UniValue getalldata(const UniValue& params, bool fHelp,const CPubKey&)
for (auto addr : zs_addresses) {
libzcash::SaplingExtendedSpendingKey extsk;
if (pwalletMain->GetSaplingExtendedSpendingKey(addr, extsk)) {
auto pt = libzcash::SaplingNotePlaintext::decrypt(
auto pt = libzcash::SaplingNotePlaintext::decrypt( Params().GetConsensus(), chainActive.Height(),
wtx.vShieldedOutput[op.n].encCiphertext,extsk.expsk.full_viewing_key().in_viewing_key(),wtx.vShieldedOutput[op.n].ephemeralKey,wtx.vShieldedOutput[op.n].cm);
if (txType == 0 && pwalletMain->IsLockedNote(op))
@ -4804,7 +4804,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp, const CPubKey& my
}
auto op = res->second;
auto wtxPrev = pwalletMain->mapWallet.at(op.hash);
auto decrypted = wtxPrev.DecryptSaplingNote(op).get();
auto decrypted = wtxPrev.DecryptSaplingNote(Params().GetConsensus(), chainActive.Height(), op).get();
auto notePt = decrypted.first;
auto pa = decrypted.second;
@ -4840,14 +4840,14 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp, const CPubKey& my
SaplingPaymentAddress pa;
bool isOutgoing;
auto decrypted = wtx.DecryptSaplingNote(op);
auto decrypted = wtx.DecryptSaplingNote(Params().GetConsensus(), chainActive.Height(), op);
if (decrypted) {
notePt = decrypted->first;
pa = decrypted->second;
isOutgoing = false;
} else {
// Try recovering the output
auto recovered = wtx.RecoverSaplingNote(op, ovks);
auto recovered = wtx.RecoverSaplingNote(Params().GetConsensus(), chainActive.Height(), op, ovks);
if (recovered) {
notePt = recovered->first;
pa = recovered->second;

187
src/wallet/wallet.cpp

@ -960,6 +960,13 @@ int64_t CWallet::NullifierCount()
return pcoinsTip->getNullifiers().size();
}
void CWallet::AddToSifted(const uint256& wtxid)
{
CWalletTx& wtx = mapWallet.at(wtxid);
if (!wtx.mapSaplingNoteData.empty())
setSiftedSapling.emplace(wtxid);
}
void CWallet::ClearNoteWitnessCache()
{
@ -1132,6 +1139,13 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO
return nMinimumHeight;
}
static SaplingWitness AppendSingleSaplingCommitment(const SaplingWitness& witness, const uint256& commitment)
{
SaplingWitness sw(witness);
sw.append(commitment);
return sw;
}
void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly)
{
@ -1169,12 +1183,26 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly)
pcoinsTip->GetSaplingAnchorAt(saplingRoot, saplingTree);
//Cycle through blocks and transactions building sapling tree until the commitment needed is reached
const CBlock *pblock;
CBlock block;
if (!ReadBlockFromDisk(block, pblockindex, 1)) {
throw std::runtime_error(
strprintf("Cannot read block height %d (%s) from disk", pindex->GetHeight(), pindex->GetBlockHash().GetHex()));
}
else {
pblock = &block;
}
std::vector<uint256> vSaplingCommitments;
std::vector<SaplingNoteData*> vSaplingNoteData;
if (setSiftedSapling.size()) {
for (const CTransaction &tx : pblock->vtx) {
for (const OutputDescription &outdesc : tx.vShieldedOutput) {
vSaplingCommitments.emplace_back(outdesc.cm);
}
}
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
if (wtxItem.second.mapSaplingNoteData.empty())
@ -1192,18 +1220,29 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly)
while (nd->witnesses.size() > WITNESS_CACHE_SIZE) {
nd->witnesses.pop_back();
}
for (const CTransaction& tx : block.vtx) {
for (uint32_t i = 0; i < tx.vShieldedOutput.size(); i++) {
const uint256& note_commitment = tx.vShieldedOutput[i].cm;
nd->witnesses.front().append(note_commitment);
}
}
// for async append of commitments
vSaplingNoteData.push_back(nd);
nd->witnessHeight = pblockindex->GetHeight();
}
}
}
// Parallelization with std::async
std::vector<std::future<SaplingWitness>> vSaplingWitnessFutures;
for (const auto& commitment : vSaplingCommitments) {
for (auto pnd : vSaplingNoteData) {
vSaplingWitnessFutures.emplace_back(std::async(std::launch::async, AppendSingleSaplingCommitment, pnd->witnesses.front(), commitment));
}
assert(vSaplingWitnessFutures.size() == vSaplingNoteData.size());
for (int i = 0; i < vSaplingWitnessFutures.size(); i++) {
vSaplingNoteData.at(i)->witnesses.front() = vSaplingWitnessFutures.at(i).get();
}
vSaplingWitnessFutures.resize(0);
}
}
if (pblockindex == pindex)
@ -1212,7 +1251,7 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly)
pblockindex = chainActive.Next(pblockindex);
}
}
}
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
@ -1417,7 +1456,7 @@ void CWallet::UpdateSaplingNullifierNoteMapWithTx(CWalletTx& wtx) {
if (mapSaplingFullViewingKeys.count(nd.ivk) != 0) {
SaplingFullViewingKey fvk = mapSaplingFullViewingKeys.at(nd.ivk);
OutputDescription output = wtx.vShieldedOutput[op.n];
auto optPlaintext = SaplingNotePlaintext::decrypt(output.encCiphertext, nd.ivk, output.ephemeralKey, output.cm);
auto optPlaintext = SaplingNotePlaintext::decrypt(Params().GetConsensus(), chainActive.Height(), output.encCiphertext, nd.ivk, output.ephemeralKey, output.cm);
if (!optPlaintext) {
// An item in mapSaplingNoteData must have already been successfully decrypted,
// otherwise the item would not exist in the first place.
@ -1466,6 +1505,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
mapWallet[hash].BindWallet(this);
UpdateNullifierNoteMapWithTx(mapWallet[hash]);
AddToSpends(hash);
AddToSifted(hash);
}
else
{
@ -1558,9 +1598,13 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
// Write to disk
if (fInsertedNew || fUpdated)
{
AddToSifted(hash);
if (!wtx.WriteToDisk(pwalletdb))
return false;
}
// Break debit/credit balance caches:
wtx.MarkDirty();
@ -1608,7 +1652,7 @@ bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx)
* If fUpdate is true, existing transactions will be updated.
*/
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, const int nHeight, bool fUpdate)
{
if(fDebug)
fprintf(stderr,"%s: tx=%s\n", __func__, tx.GetHash().ToString().c_str() );
@ -1619,7 +1663,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
return false;
bool fExisted = mapWallet.count(tx.GetHash()) != 0;
if (fExisted && !fUpdate) return false;
auto saplingNoteDataAndAddressesToAdd = FindMySaplingNotes(tx);
std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> saplingNoteDataAndAddressesToAdd;
saplingNoteDataAndAddressesToAdd = fAsyncNoteDecryption ? FindMySaplingNotesAsync(tx, nHeight) : FindMySaplingNotes(tx);
auto saplingNoteData = saplingNoteDataAndAddressesToAdd.first;
auto addressesToAdd = saplingNoteDataAndAddressesToAdd.second;
for (const auto &addressToAdd : addressesToAdd) {
@ -1689,12 +1734,12 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
return false;
}
void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock, const int nHeight)
{
LOCK(cs_wallet);
if(fDebug)
fprintf(stderr,"%s: tx=%s\n", __func__, tx.GetHash().ToString().c_str() );
if (!AddToWalletIfInvolvingMe(tx, pblock, true))
if (!AddToWalletIfInvolvingMe(tx, pblock, nHeight, true))
return; // Not one of ours
MarkAffectedTransactionsDirty(tx);
@ -1777,7 +1822,7 @@ std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> CWallet::FindMySap
bool found = false;
for (auto it = mapSaplingFullViewingKeys.begin(); it != mapSaplingFullViewingKeys.end(); ++it) {
SaplingIncomingViewingKey ivk = it->first;
auto result = SaplingNotePlaintext::decrypt(output.encCiphertext, ivk, output.ephemeralKey, output.cm);
auto result = SaplingNotePlaintext::decrypt(Params().GetConsensus(), chainActive.Height(), output.encCiphertext, ivk, output.ephemeralKey, output.cm);
if (result) {
auto address = ivk.address(result.get().d);
if (address && mapSaplingIncomingViewingKeys.count(address.get()) == 0) {
@ -1796,7 +1841,7 @@ std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> CWallet::FindMySap
if (!found) {
for (auto it = mapSaplingIncomingViewingKeys.begin(); it != mapSaplingIncomingViewingKeys.end(); ++it) {
SaplingIncomingViewingKey ivk = it-> second;
auto result = SaplingNotePlaintext::decrypt(output.encCiphertext, ivk, output.ephemeralKey, output.cm);
auto result = SaplingNotePlaintext::decrypt(Params().GetConsensus(), chainActive.Height(), output.encCiphertext, ivk, output.ephemeralKey, output.cm);
if (!result) {
continue;
}
@ -1814,6 +1859,103 @@ std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> CWallet::FindMySap
return std::make_pair(noteData, viewingKeysToAdd);
}
static std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> DecryptSaplingNoteWorker(const Consensus::Params &consensus_params, const SaplingIncomingViewingKey &ivk, const OutputDescription &outdesc, const int &height, const uint256 &hash, const uint32_t &i)
{
mapSaplingNoteData_t noteData;
SaplingIncomingViewingKeyMap viewingKeysToAdd;
auto result = SaplingNotePlaintext::decrypt(consensus_params, height, outdesc.encCiphertext, ivk, outdesc.ephemeralKey, outdesc.cm);
if (result)
{
// We don't cache the nullifier here as computing it requires knowledge of the note position
// in the commitment tree, which can only be determined when the transaction has been mined.
SaplingOutPoint op {hash, i};
SaplingNoteData nd;
nd.ivk = ivk;
noteData.insert(std::make_pair(op, nd));
auto address = ivk.address(result.value().d);
if (address)
{
viewingKeysToAdd.insert(make_pair(address.value(), ivk));
}
}
return std::make_pair(noteData, viewingKeysToAdd);
}
/**
* Finds all output notes in the given transaction that have been sent to
* SaplingPaymentAddresses in this wallet.
*
* It should never be necessary to call this method with a CWalletTx, because
* the result of FindMySaplingNotes (for the addresses available at the time) will
* already have been cached in CWalletTx.mapSaplingNoteData.
*/
std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> CWallet::FindMySaplingNotesAsync(const CTransaction &tx, int height) const
{
mapSaplingNoteData_t noteData;
SaplingIncomingViewingKeyMap viewingKeysToAdd;
if (tx.vShieldedOutput.empty())
{
return std::make_pair(noteData, viewingKeysToAdd);
}
LOCK(cs_KeyStore);
std::set<SaplingIncomingViewingKey> setSaplingIvkToTest;
for (const auto& [ivk, fvk] : mapSaplingFullViewingKeys)
{
setSaplingIvkToTest.insert(ivk);
}
for (const auto& [address, ivk] : mapSaplingIncomingViewingKeys)
{
setSaplingIvkToTest.insert(ivk);
}
if (setSaplingIvkToTest.empty())
{
return std::make_pair(noteData, viewingKeysToAdd);
}
std::vector<std::future<std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap>>> vDecryptFutures;
const Consensus::Params consensus_params = Params().GetConsensus();
uint256 hash = tx.GetHash();
// Protocol Spec: 4.19 Block Chain Scanning (Sapling)
for (uint32_t i = 0; i < tx.vShieldedOutput.size(); ++i)
{
const OutputDescription output = tx.vShieldedOutput[i];
for (SaplingIncomingViewingKey ivk : setSaplingIvkToTest)
{
vDecryptFutures.emplace_back(std::async(std::launch::async, DecryptSaplingNoteWorker, consensus_params, ivk, output, height, hash, i));
}
}
for (auto &fut : vDecryptFutures)
{
auto result_pair = fut.get();
if (!result_pair.first.empty())
{
noteData.insert(result_pair.first.begin(), result_pair.first.end());
for (auto [address, ivk] : result_pair.second)
{
if (mapSaplingIncomingViewingKeys.count(address) == 0)
{
viewingKeysToAdd[address] = ivk;
}
}
}
}
return std::make_pair(noteData, viewingKeysToAdd);
}
bool CWallet::IsSaplingNullifierFromMe(const uint256& nullifier) const
{
{
@ -2221,7 +2363,7 @@ void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t &noteData)
boost::optional<std::pair<
SaplingNotePlaintext,
SaplingPaymentAddress>> CWalletTx::DecryptSaplingNote(SaplingOutPoint op) const
SaplingPaymentAddress>> CWalletTx::DecryptSaplingNote(const Consensus::Params& params, int height, SaplingOutPoint op) const
{
// Check whether we can decrypt this SaplingOutPoint
if (this->mapSaplingNoteData.count(op) == 0) {
@ -2232,6 +2374,8 @@ boost::optional<std::pair<
auto nd = this->mapSaplingNoteData.at(op);
auto maybe_pt = SaplingNotePlaintext::decrypt(
params,
height,
output.encCiphertext,
nd.ivk,
output.ephemeralKey,
@ -2248,8 +2392,7 @@ boost::optional<std::pair<
boost::optional<std::pair<
SaplingNotePlaintext,
SaplingPaymentAddress>> CWalletTx::RecoverSaplingNote(
SaplingOutPoint op, std::set<uint256>& ovks) const
SaplingPaymentAddress>> CWalletTx::RecoverSaplingNote(const Consensus::Params& params, int height, SaplingOutPoint op, std::set<uint256>& ovks) const
{
auto output = this->vShieldedOutput[op.n];
@ -2265,6 +2408,8 @@ boost::optional<std::pair<
}
auto maybe_pt = SaplingNotePlaintext::decrypt(
params,
height,
output.encCiphertext,
output.ephemeralKey,
outPt->esk,
@ -2780,7 +2925,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) {
if (AddToWalletIfInvolvingMe(tx, &block, pindex->GetHeight(), fUpdate)) {
involvesMe = true;
ret++;
}
@ -4918,6 +5063,8 @@ void CWallet::GetFilteredNotes(
SaplingNoteData nd = pair.second;
auto maybe_pt = SaplingNotePlaintext::decrypt(
Params().GetConsensus(),
chainActive.Height(),
wtx.vShieldedOutput[op.n].encCiphertext,
nd.ivk,
wtx.vShieldedOutput[op.n].ephemeralKey,

13
src/wallet/wallet.h

@ -575,10 +575,10 @@ public:
boost::optional<std::pair<
libzcash::SaplingNotePlaintext,
libzcash::SaplingPaymentAddress>> DecryptSaplingNote(SaplingOutPoint op) const;
libzcash::SaplingPaymentAddress>> DecryptSaplingNote(const Consensus::Params& params, int height, SaplingOutPoint op) const;
boost::optional<std::pair<
libzcash::SaplingNotePlaintext,
libzcash::SaplingPaymentAddress>> RecoverSaplingNote(
libzcash::SaplingPaymentAddress>> RecoverSaplingNote(const Consensus::Params& params, int height,
SaplingOutPoint op, std::set<uint256>& ovks) const;
//! filter decides which addresses will count towards the debit
@ -1015,6 +1015,9 @@ public:
std::map<uint256, SaplingOutPoint> mapSaplingNullifiersToNotes;
std::map<uint256, CWalletTx> mapWallet;
std::set<uint256> setSiftedSapling;
void AddToSifted(const uint256& wtxid);
int64_t nOrderPosNext;
std::map<CTxDestination, CAddressBookData> mapAddressBook;
@ -1151,9 +1154,9 @@ public:
void UpdateNullifierNoteMapForBlock(const CBlock* pblock);
bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
void EraseFromWallet(const uint256 &hash);
void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
void SyncTransaction(const CTransaction& tx, const CBlock* pblock, const int nHeight);
void RescanWallet();
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, const int nHeight, bool fUpdate);
void ReorderWalletTransactions(std::map<std::pair<int,int>, CWalletTx*> &mapSorted, int64_t &maxOrderPos);
void UpdateWalletTransactionOrder(std::map<std::pair<int,int>, CWalletTx*> &mapSorted, bool resetOrder);
void DeleteTransactions(std::vector<uint256> &removeTxs);
@ -1191,6 +1194,8 @@ public:
std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> FindMySaplingNotes(const CTransaction& tx) const;
std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> FindMySaplingNotesAsync(const CTransaction& tx, int height) const;
bool IsSaplingNullifierFromMe(const uint256& nullifier) const;
void GetSaplingNoteWitnesses(

4
src/zcash/Note.cpp

@ -116,6 +116,8 @@ boost::optional<SaplingOutgoingPlaintext> SaplingOutgoingPlaintext::decrypt(
}
boost::optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
const Consensus::Params& params,
int height,
const SaplingEncCiphertext &ciphertext,
const uint256 &ivk,
const uint256 &epk,
@ -165,6 +167,8 @@ boost::optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
}
boost::optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
const Consensus::Params& params,
int height,
const SaplingEncCiphertext &ciphertext,
const uint256 &epk,
const uint256 &esk,

6
src/zcash/Note.hpp

@ -9,6 +9,8 @@
#include "Zcash.h"
#include "Address.hpp"
#include "NoteEncryption.hpp"
#include "consensus/params.h"
#include "consensus/consensus.h"
#include <array>
#include <boost/optional.hpp>
@ -71,6 +73,8 @@ public:
SaplingNotePlaintext(const SaplingNote& note, std::array<unsigned char, HUSH_MEMO_SIZE> memo);
static boost::optional<SaplingNotePlaintext> decrypt(
const Consensus::Params& params,
int height,
const SaplingEncCiphertext &ciphertext,
const uint256 &ivk,
const uint256 &epk,
@ -78,6 +82,8 @@ public:
);
static boost::optional<SaplingNotePlaintext> decrypt(
const Consensus::Params& params,
int height,
const SaplingEncCiphertext &ciphertext,
const uint256 &epk,
const uint256 &esk,

Loading…
Cancel
Save