Merge pull request 'Implement zsweep' (#195) from zsweep into dev

Reviewed-on: https://git.hush.is/hush/hush3/pulls/195
This commit is contained in:
Duke Leto
2022-09-17 02:16:05 +00:00
28 changed files with 754 additions and 60 deletions

View File

@@ -59,6 +59,7 @@
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#include "wallet/asyncrpcoperation_saplingconsolidation.h"
#include "wallet/asyncrpcoperation_sweep.h"
#endif
#include <stdint.h>
#include <stdio.h>
@@ -444,6 +445,17 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-consolidation", _("Enable auto Sapling note consolidation (default: false)"));
strUsage += HelpMessageOpt("-consolidatesaplingaddress=<zaddr>", _("Specify Sapling Address to Consolidate. (default: all)"));
strUsage += HelpMessageOpt("-consolidationtxfee", strprintf(_("Fee amount in Puposhis used send consolidation transactions. (default %i)"), DEFAULT_CONSOLIDATION_FEE));
strUsage += HelpMessageOpt("-zsweep", _("Enable zaddr sweeping, automatically move all shielded funds to a one address once per X blocks"));
strUsage += HelpMessageOpt("-zsweepaddress=<zaddr>", _("Specify the shielded address where swept funds will be sent)"));
strUsage += HelpMessageOpt("-zsweepfee", strprintf(_("Fee amount in puposhis used send sweep transactions. (default %i)"), DEFAULT_SWEEP_FEE));
strUsage += HelpMessageOpt("-zsweepinterval", strprintf(_("Sweep shielded funds every X blocks (default %i)"), 5));
strUsage += HelpMessageOpt("-zsweepmaxinputs", strprintf(_("Maximum number of shielded inputs to sweep per transaction (default %i)"), 8));
// By default we only allow sweeping to the current wallet which must have the spending key of the sweep zaddr
// This hopefully will make it harder for people to accidentally sweep funds to a wrong zaddr and lose funds
strUsage += HelpMessageOpt("-zsweepexternal", _("Enable sweeping to an external wallet (default false)"));
strUsage += HelpMessageOpt("-zsweepexclude", _("Addresses to exclude from sweeping (default none)"));
strUsage += HelpMessageOpt("-deletetx", _("Enable Old Transaction Deletion"));
strUsage += HelpMessageOpt("-deleteinterval", strprintf(_("Delete transaction every <n> blocks during inital block download (default: %i)"), DEFAULT_TX_DELETE_INTERVAL));
strUsage += HelpMessageOpt("-keeptxnum", strprintf(_("Keep the last <n> transactions (default: %i)"), DEFAULT_TX_RETENTION_LASTTX));
@@ -2008,16 +2020,101 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
//Set Sapling Consolidation
pwalletMain->fSaplingConsolidationEnabled = GetBoolArg("-consolidation", false);
fConsolidationTxFee = GetArg("-consolidationtxfee", DEFAULT_CONSOLIDATION_FEE);
fConsolidationMapUsed = !mapMultiArgs["-consolidatesaplingaddress"].empty();
if(pwalletMain->fSaplingConsolidationEnabled) {
fConsolidationTxFee = GetArg("-consolidationtxfee", DEFAULT_CONSOLIDATION_FEE);
fConsolidationMapUsed = !mapMultiArgs["-consolidatesaplingaddress"].empty();
//Validate Sapling Addresses
vector<string>& vaddresses = mapMultiArgs["-consolidatesaplingaddress"];
for (int i = 0; i < vaddresses.size(); i++) {
LogPrintf("Consolidating Sapling Address: %s\n", vaddresses[i]);
auto zAddress = DecodePaymentAddress(vaddresses[i]);
if (!IsValidPaymentAddress(zAddress)) {
return InitError("Invalid consolidation address");
int consolidationInterval = GetArg("-consolidationinterval", 25);
if (consolidationInterval < 5) {
fprintf(stderr,"%s: Invalid consolidation interval of %d < 5, setting to default of 25\n", __func__, consolidationInterval);
consolidationInterval = 25;
}
pwalletMain->consolidationInterval = consolidationInterval;
pwalletMain->nextConsolidation = pwalletMain->consolidationInterval + chainActive.Tip()->GetHeight();
LogPrintf("%s: set nextConsolidation=%d\n", __func__, pwalletMain->nextConsolidation );
//Validate Sapling Addresses
vector<string>& vaddresses = mapMultiArgs["-consolidatesaplingaddress"];
for (int i = 0; i < vaddresses.size(); i++) {
LogPrintf("Consolidating Sapling Address: %s\n", vaddresses[i]);
auto zAddress = DecodePaymentAddress(vaddresses[i]);
if (!IsValidPaymentAddress(zAddress)) {
return InitError("Invalid consolidation address");
}
}
}
//Set Sweep
pwalletMain->fSweepEnabled = GetBoolArg("-zsweep", false);
if (pwalletMain->fSweepEnabled) {
int sweepInterval = GetArg("-zsweepinterval", 10);
if (sweepInterval < 5) {
fprintf(stderr,"%s: Invalid sweep interval of %d, setting to default of 10\n", __func__, sweepInterval);
sweepInterval = 10;
}
pwalletMain->sweepInterval = sweepInterval;
pwalletMain->nextSweep = pwalletMain->sweepInterval + chainActive.Tip()->GetHeight();
LogPrintf("%s: set nextSweep=%d with sweepInterval=%d\n", __func__, pwalletMain->nextSweep, pwalletMain->sweepInterval );
fSweepTxFee = GetArg("-zsweepfee", DEFAULT_SWEEP_FEE);
fSweepMapUsed = !mapMultiArgs["-zsweepaddress"].empty();
//Validate Sapling Addresses
vector<string>& vSweep = mapMultiArgs["-zsweepaddress"];
vector<string>& vSweepExclude = mapMultiArgs["-zsweepexclude"];
if (vSweep.size() != 1) {
return InitError("A single zsweep address must be specified.");
}
for (int i = 0; i < vSweep.size(); i++) {
// LogPrintf("Sweep Address: %s\n", vSweep[i]);
auto zSweep = DecodePaymentAddress(vSweep[i]);
if (!IsValidPaymentAddress(zSweep)) {
return InitError("Invalid zsweep address");
}
auto hasSpendingKey = boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), zSweep);
auto allowSweepToExternalWallet = GetArg("-zsweepexternal", false);
pwalletMain->sweepAddress = vSweep[i];
if (!hasSpendingKey) {
if (allowSweepToExternalWallet) {
LogPrintf("%s: sweeping funds to a zaddr in an external wallet\n", __func__);
} else {
return InitError("Wallet must have the spending key of zsweep address");
}
}
}
for (int i = 0; i < vSweepExclude.size(); i++) {
LogPrintf("Sweep Excluded Address: %s\n", vSweepExclude[i]);
auto zSweepExcluded = DecodePaymentAddress(vSweepExclude[i]);
if (!IsValidPaymentAddress(zSweepExcluded)) {
return InitError("Invalid zsweepexclude address");
}
auto hasSpendingKey = boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), zSweepExcluded);
if (!hasSpendingKey) {
return InitError("Wallet must have the spending key of zsweepexclude address");
}
// Add this validated zaddr to the list of excluded sweep zaddrs
pwalletMain->sweepExcludeAddresses.push_back( vSweepExclude[i] );
}
if (pwalletMain->fSaplingConsolidationEnabled) {
//Validate 1 Consolidation address only that matches the sweep address
vector<string>& vaddresses = mapMultiArgs["-consolidatesaplingaddress"];
if (vaddresses.size() == 0) {
fConsolidationMapUsed = true;
mapMultiArgs["-consolidatesaplingaddress"] = vSweep;
} else {
pwalletMain->consolidationAddress = vaddresses[0];
for (int i = 0; i < vaddresses.size(); i++) {
if (vSweep[0] != vaddresses[i]) {
return InitError("Consolidation can only be used on the sweep address when sweep is enabled.");
}
}
}
}
}