Auto merge of #4270 - str4d:2074-wallet-2, r=str4d
Bitcoin wallet PRs 2 Cherry-picked from the following upstream PRs: - bitcoin/bitcoin#7576 - bitcoin/bitcoin#7577 - bitcoin/bitcoin#7608 - bitcoin/bitcoin#7691 - bitcoin/bitcoin#7905
This commit is contained in:
commit
fa341bcff0
|
@ -177,6 +177,7 @@ BITCOIN_CORE_H = \
|
||||||
script/sigcache.h \
|
script/sigcache.h \
|
||||||
script/sign.h \
|
script/sign.h \
|
||||||
script/standard.h \
|
script/standard.h \
|
||||||
|
script/ismine.h \
|
||||||
serialize.h \
|
serialize.h \
|
||||||
spentindex.h \
|
spentindex.h \
|
||||||
streams.h \
|
streams.h \
|
||||||
|
@ -217,7 +218,6 @@ BITCOIN_CORE_H = \
|
||||||
wallet/paymentdisclosuredb.h \
|
wallet/paymentdisclosuredb.h \
|
||||||
wallet/rpcwallet.h \
|
wallet/rpcwallet.h \
|
||||||
wallet/wallet.h \
|
wallet/wallet.h \
|
||||||
wallet/wallet_ismine.h \
|
|
||||||
wallet/walletdb.h \
|
wallet/walletdb.h \
|
||||||
zmq/zmqabstractnotifier.h \
|
zmq/zmqabstractnotifier.h \
|
||||||
zmq/zmqconfig.h\
|
zmq/zmqconfig.h\
|
||||||
|
@ -266,6 +266,7 @@ libbitcoin_server_a_SOURCES = \
|
||||||
rpc/rawtransaction.cpp \
|
rpc/rawtransaction.cpp \
|
||||||
rpc/server.cpp \
|
rpc/server.cpp \
|
||||||
script/sigcache.cpp \
|
script/sigcache.cpp \
|
||||||
|
script/ismine.cpp \
|
||||||
timedata.cpp \
|
timedata.cpp \
|
||||||
torcontrol.cpp \
|
torcontrol.cpp \
|
||||||
txdb.cpp \
|
txdb.cpp \
|
||||||
|
@ -312,7 +313,6 @@ libbitcoin_wallet_a_SOURCES = \
|
||||||
wallet/rpcdump.cpp \
|
wallet/rpcdump.cpp \
|
||||||
wallet/rpcwallet.cpp \
|
wallet/rpcwallet.cpp \
|
||||||
wallet/wallet.cpp \
|
wallet/wallet.cpp \
|
||||||
wallet/wallet_ismine.cpp \
|
|
||||||
wallet/walletdb.cpp \
|
wallet/walletdb.cpp \
|
||||||
$(BITCOIN_CORE_H) \
|
$(BITCOIN_CORE_H) \
|
||||||
$(LIBZCASH_H)
|
$(LIBZCASH_H)
|
||||||
|
|
|
@ -108,9 +108,11 @@ BITCOIN_TESTS =\
|
||||||
|
|
||||||
if ENABLE_WALLET
|
if ENABLE_WALLET
|
||||||
BITCOIN_TESTS += \
|
BITCOIN_TESTS += \
|
||||||
test/accounting_tests.cpp \
|
wallet/test/wallet_test_fixture.cpp \
|
||||||
|
wallet/test/wallet_test_fixture.h \
|
||||||
|
wallet/test/accounting_tests.cpp \
|
||||||
wallet/test/wallet_tests.cpp \
|
wallet/test/wallet_tests.cpp \
|
||||||
test/rpc_wallet_tests.cpp
|
wallet/test/rpc_wallet_tests.cpp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
|
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
|
||||||
|
|
272
src/init.cpp
272
src/init.cpp
|
@ -77,16 +77,12 @@ extern void ThreadSendAlert();
|
||||||
|
|
||||||
ZCJoinSplit* pzcashParams = NULL;
|
ZCJoinSplit* pzcashParams = NULL;
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
CWallet* pwalletMain = NULL;
|
|
||||||
#endif
|
|
||||||
bool fFeeEstimatesInitialized = false;
|
bool fFeeEstimatesInitialized = false;
|
||||||
static const bool DEFAULT_PROXYRANDOMIZE = true;
|
static const bool DEFAULT_PROXYRANDOMIZE = true;
|
||||||
static const bool DEFAULT_REST_ENABLE = false;
|
static const bool DEFAULT_REST_ENABLE = false;
|
||||||
static const bool DEFAULT_DISABLE_SAFEMODE = false;
|
static const bool DEFAULT_DISABLE_SAFEMODE = false;
|
||||||
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
|
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
|
||||||
|
|
||||||
static const char * const DEFAULT_WALLET_DAT = "wallet.dat";
|
|
||||||
|
|
||||||
#if ENABLE_ZMQ
|
#if ENABLE_ZMQ
|
||||||
static CZMQNotificationInterface* pzmqNotificationInterface = NULL;
|
static CZMQNotificationInterface* pzmqNotificationInterface = NULL;
|
||||||
|
@ -411,27 +407,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
" " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway"));
|
" " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway"));
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
strUsage += HelpMessageGroup(_("Wallet options:"));
|
strUsage += CWallet::GetWalletHelpString(showDebug);
|
||||||
strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
|
|
||||||
strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
|
|
||||||
strUsage += HelpMessageOpt("-migration", _("Enable the Sprout to Sapling migration"));
|
|
||||||
strUsage += HelpMessageOpt("-migrationdestaddress=<zaddr>", _("Set the Sapling migration address"));
|
|
||||||
strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
|
|
||||||
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
|
|
||||||
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
|
|
||||||
CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
|
|
||||||
strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions on startup"));
|
|
||||||
strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat on startup"));
|
|
||||||
strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS));
|
|
||||||
strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
|
|
||||||
strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
|
|
||||||
strUsage += HelpMessageOpt("-txexpirydelta", strprintf(_("Set the number of blocks after which a transaction that has not been mined will become invalid (min: %u, default: %u (pre-Blossom) or %u (post-Blossom))"), TX_EXPIRING_SOON_THRESHOLD + 1, DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA));
|
|
||||||
strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup"));
|
|
||||||
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
|
|
||||||
strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST));
|
|
||||||
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
|
|
||||||
strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
|
|
||||||
" " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_ZMQ
|
#if ENABLE_ZMQ
|
||||||
|
@ -454,16 +430,10 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
if (showDebug)
|
if (showDebug)
|
||||||
{
|
{
|
||||||
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED));
|
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED));
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
|
|
||||||
#endif
|
|
||||||
strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE));
|
strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE));
|
||||||
strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE));
|
strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE));
|
||||||
strUsage += HelpMessageOpt("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages");
|
strUsage += HelpMessageOpt("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages");
|
||||||
strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", "Randomly fuzz 1 of every <n> network messages");
|
strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", "Randomly fuzz 1 of every <n> network messages");
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET));
|
|
||||||
#endif
|
|
||||||
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT));
|
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT));
|
||||||
strUsage += HelpMessageOpt("-nuparams=hexBranchId:activationHeight", "Use given activation height for specified network upgrade (regtest-only)");
|
strUsage += HelpMessageOpt("-nuparams=hexBranchId:activationHeight", "Use given activation height for specified network upgrade (regtest-only)");
|
||||||
}
|
}
|
||||||
|
@ -490,9 +460,6 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
if (showDebug)
|
if (showDebug)
|
||||||
{
|
{
|
||||||
strUsage += HelpMessageOpt("-printpriority", strprintf("Log transaction priority and fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY));
|
strUsage += HelpMessageOpt("-printpriority", strprintf("Log transaction priority and fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY));
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
// strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)"));
|
// strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)"));
|
||||||
|
|
||||||
|
@ -1042,63 +1009,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if (mapArgs.count("-mintxfee"))
|
if (!CWallet::ParameterInteraction())
|
||||||
{
|
return false;
|
||||||
CAmount n = 0;
|
|
||||||
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
|
|
||||||
CWallet::minTxFee = CFeeRate(n);
|
|
||||||
else
|
|
||||||
return InitError(strprintf(_("Invalid amount for -mintxfee=<amount>: '%s'"), mapArgs["-mintxfee"]));
|
|
||||||
}
|
|
||||||
if (mapArgs.count("-paytxfee"))
|
|
||||||
{
|
|
||||||
CAmount nFeePerK = 0;
|
|
||||||
if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
|
|
||||||
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"]));
|
|
||||||
if (nFeePerK > HIGH_TX_FEE_PER_KB)
|
|
||||||
InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
|
|
||||||
payTxFee = CFeeRate(nFeePerK, 1000);
|
|
||||||
if (payTxFee < ::minRelayTxFee)
|
|
||||||
{
|
|
||||||
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
|
|
||||||
mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mapArgs.count("-maxtxfee"))
|
|
||||||
{
|
|
||||||
CAmount nMaxFee = 0;
|
|
||||||
if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee))
|
|
||||||
return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s'"), mapArgs["-maptxfee"]));
|
|
||||||
if (nMaxFee > HIGH_MAX_TX_FEE)
|
|
||||||
InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
|
|
||||||
maxTxFee = nMaxFee;
|
|
||||||
if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
|
|
||||||
{
|
|
||||||
return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
|
|
||||||
mapArgs["-maxtxfee"], ::minRelayTxFee.ToString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
|
|
||||||
if (mapArgs.count("-txexpirydelta")) {
|
|
||||||
int64_t expiryDelta = atoi64(mapArgs["-txexpirydelta"]);
|
|
||||||
uint32_t minExpiryDelta = TX_EXPIRING_SOON_THRESHOLD + 1;
|
|
||||||
if (expiryDelta < minExpiryDelta) {
|
|
||||||
return InitError(strprintf(_("Invalid value for -txexpirydelta='%u' (must be least %u)"), expiryDelta, minExpiryDelta));
|
|
||||||
}
|
|
||||||
expiryDeltaArg = expiryDelta;
|
|
||||||
}
|
|
||||||
bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
|
|
||||||
fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS);
|
|
||||||
|
|
||||||
std::string strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
|
|
||||||
// Check Sapling migration address if set and is a valid Sapling address
|
|
||||||
if (mapArgs.count("-migrationdestaddress")) {
|
|
||||||
std::string migrationDestAddress = mapArgs["-migrationdestaddress"];
|
|
||||||
libzcash::PaymentAddress address = DecodePaymentAddress(migrationDestAddress);
|
|
||||||
if (boost::get<libzcash::SaplingPaymentAddress>(&address) == nullptr) {
|
|
||||||
return InitError(_("-migrationdestaddress must be a valid Sapling address."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // ENABLE_WALLET
|
#endif // ENABLE_WALLET
|
||||||
|
|
||||||
fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
|
fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
|
||||||
|
@ -1175,11 +1087,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
return InitError(_("Initialization sanity check failed. Zcash is shutting down."));
|
return InitError(_("Initialization sanity check failed. Zcash is shutting down."));
|
||||||
|
|
||||||
std::string strDataDir = GetDataDir().string();
|
std::string strDataDir = GetDataDir().string();
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
// Wallet file must be a plain filename without a directory
|
|
||||||
if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile))
|
|
||||||
return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir));
|
|
||||||
#endif
|
|
||||||
// Make sure only a single Bitcoin process is using the data directory.
|
// Make sure only a single Bitcoin process is using the data directory.
|
||||||
boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
|
boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
|
||||||
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
|
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
|
||||||
|
@ -1255,20 +1163,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
// ********************************************************* Step 5: verify wallet database integrity
|
// ********************************************************* Step 5: verify wallet database integrity
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if (!fDisableWallet) {
|
if (!fDisableWallet) {
|
||||||
LogPrintf("Using wallet %s\n", strWalletFile);
|
if (!CWallet::Verify())
|
||||||
uiInterface.InitMessage(_("Verifying wallet..."));
|
|
||||||
|
|
||||||
std::string warningString;
|
|
||||||
std::string errorString;
|
|
||||||
|
|
||||||
if (!CWallet::Verify(strWalletFile, warningString, errorString))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!warningString.empty())
|
|
||||||
InitWarning(warningString);
|
|
||||||
if (!errorString.empty())
|
|
||||||
return InitError(errorString);
|
|
||||||
|
|
||||||
} // (!fDisableWallet)
|
} // (!fDisableWallet)
|
||||||
#endif // ENABLE_WALLET
|
#endif // ENABLE_WALLET
|
||||||
// ********************************************************* Step 6: network initialization
|
// ********************************************************* Step 6: network initialization
|
||||||
|
@ -1593,164 +1489,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
pwalletMain = NULL;
|
pwalletMain = NULL;
|
||||||
LogPrintf("Wallet disabled!\n");
|
LogPrintf("Wallet disabled!\n");
|
||||||
} else {
|
} else {
|
||||||
|
CWallet::InitLoadWallet(clearWitnessCaches);
|
||||||
// needed to restore wallet transaction meta data after -zapwallettxes
|
if (!pwalletMain)
|
||||||
std::vector<CWalletTx> vWtx;
|
|
||||||
|
|
||||||
if (GetBoolArg("-zapwallettxes", false)) {
|
|
||||||
uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
|
|
||||||
|
|
||||||
pwalletMain = new CWallet(strWalletFile);
|
|
||||||
DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(vWtx);
|
|
||||||
if (nZapWalletRet != DB_LOAD_OK) {
|
|
||||||
uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted"));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pwalletMain;
|
|
||||||
pwalletMain = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uiInterface.InitMessage(_("Loading wallet..."));
|
|
||||||
|
|
||||||
nStart = GetTimeMillis();
|
|
||||||
bool fFirstRun = true;
|
|
||||||
pwalletMain = new CWallet(strWalletFile);
|
|
||||||
DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun);
|
|
||||||
if (nLoadWalletRet != DB_LOAD_OK)
|
|
||||||
{
|
|
||||||
if (nLoadWalletRet == DB_CORRUPT)
|
|
||||||
strErrors << _("Error loading wallet.dat: Wallet corrupted") << "\n";
|
|
||||||
else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
|
|
||||||
{
|
|
||||||
string msg(_("error reading wallet.dat! All keys read correctly, but transaction data"
|
|
||||||
" or address book entries might be missing or incorrect."));
|
|
||||||
InitWarning(msg);
|
|
||||||
}
|
|
||||||
else if (nLoadWalletRet == DB_TOO_NEW)
|
|
||||||
strErrors << _("Error loading wallet.dat: Wallet requires newer version of Zcash") << "\n";
|
|
||||||
else if (nLoadWalletRet == DB_NEED_REWRITE)
|
|
||||||
{
|
|
||||||
strErrors << _("Wallet needed to be rewritten: restart Zcash to complete") << "\n";
|
|
||||||
LogPrintf("%s", strErrors.str());
|
|
||||||
return InitError(strErrors.str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
strErrors << _("Error loading wallet.dat") << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetBoolArg("-upgradewallet", fFirstRun))
|
|
||||||
{
|
|
||||||
int nMaxVersion = GetArg("-upgradewallet", 0);
|
|
||||||
if (nMaxVersion == 0) // the -upgradewallet without argument case
|
|
||||||
{
|
|
||||||
LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
|
|
||||||
nMaxVersion = CLIENT_VERSION;
|
|
||||||
pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
|
|
||||||
if (nMaxVersion < pwalletMain->GetVersion())
|
|
||||||
strErrors << _("Cannot downgrade wallet") << "\n";
|
|
||||||
pwalletMain->SetMaxVersion(nMaxVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pwalletMain->HaveHDSeed())
|
|
||||||
{
|
|
||||||
// We can't set the new HD seed until the wallet is decrypted.
|
|
||||||
// https://github.com/zcash/zcash/issues/3607
|
|
||||||
if (!pwalletMain->IsCrypted()) {
|
|
||||||
// generate a new HD seed
|
|
||||||
pwalletMain->GenerateNewSeed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set sapling migration status
|
|
||||||
pwalletMain->fSaplingMigrationEnabled = GetBoolArg("-migration", false);
|
|
||||||
|
|
||||||
if (fFirstRun)
|
|
||||||
{
|
|
||||||
// Create new keyUser and set as default key
|
|
||||||
CPubKey newDefaultKey;
|
|
||||||
if (pwalletMain->GetKeyFromPool(newDefaultKey)) {
|
|
||||||
pwalletMain->SetDefaultKey(newDefaultKey);
|
|
||||||
if (!pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive"))
|
|
||||||
strErrors << _("Cannot write default address") << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
pwalletMain->SetBestChain(chainActive.GetLocator());
|
|
||||||
}
|
|
||||||
|
|
||||||
LogPrintf("%s", strErrors.str());
|
|
||||||
LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart);
|
|
||||||
|
|
||||||
RegisterValidationInterface(pwalletMain);
|
|
||||||
|
|
||||||
CBlockIndex *pindexRescan = chainActive.Tip();
|
|
||||||
if (clearWitnessCaches || GetBoolArg("-rescan", false))
|
|
||||||
{
|
|
||||||
pwalletMain->ClearNoteWitnessCache();
|
|
||||||
pindexRescan = chainActive.Genesis();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
CBlockLocator locator;
|
|
||||||
if (walletdb.ReadBestBlock(locator))
|
|
||||||
pindexRescan = FindForkInGlobalIndex(chainActive, locator);
|
|
||||||
else
|
|
||||||
pindexRescan = chainActive.Genesis();
|
|
||||||
}
|
|
||||||
if (chainActive.Tip() && chainActive.Tip() != pindexRescan)
|
|
||||||
{
|
|
||||||
// We can't rescan beyond non-pruned blocks, so stop and throw an error.
|
|
||||||
// This might happen if a user uses a old wallet within a pruned node,
|
|
||||||
// or if they ran -disablewallet for a longer time, then decided to re-enable.
|
|
||||||
if (fPruneMode)
|
|
||||||
{
|
|
||||||
CBlockIndex *block = chainActive.Tip();
|
|
||||||
while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block)
|
|
||||||
block = block->pprev;
|
|
||||||
|
|
||||||
if (pindexRescan != block)
|
|
||||||
return InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
|
|
||||||
}
|
|
||||||
|
|
||||||
uiInterface.InitMessage(_("Rescanning..."));
|
|
||||||
LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
|
|
||||||
nStart = GetTimeMillis();
|
|
||||||
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
|
|
||||||
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
|
||||||
pwalletMain->SetBestChain(chainActive.GetLocator());
|
|
||||||
nWalletDBUpdated++;
|
|
||||||
|
|
||||||
// Restore wallet transaction metadata after -zapwallettxes=1
|
|
||||||
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
|
|
||||||
{
|
|
||||||
CWalletDB walletdb(strWalletFile);
|
|
||||||
|
|
||||||
BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
|
|
||||||
{
|
|
||||||
uint256 hash = wtxOld.GetHash();
|
|
||||||
std::map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
|
|
||||||
if (mi != pwalletMain->mapWallet.end())
|
|
||||||
{
|
|
||||||
const CWalletTx* copyFrom = &wtxOld;
|
|
||||||
CWalletTx* copyTo = &mi->second;
|
|
||||||
copyTo->mapValue = copyFrom->mapValue;
|
|
||||||
copyTo->vOrderForm = copyFrom->vOrderForm;
|
|
||||||
copyTo->nTimeReceived = copyFrom->nTimeReceived;
|
|
||||||
copyTo->nTimeSmart = copyFrom->nTimeSmart;
|
|
||||||
copyTo->fFromMe = copyFrom->fFromMe;
|
|
||||||
copyTo->strFromAccount = copyFrom->strFromAccount;
|
|
||||||
copyTo->nOrderPos = copyFrom->nOrderPos;
|
|
||||||
copyTo->WriteToDisk(&walletdb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pwalletMain->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
|
|
||||||
} // (!fDisableWallet)
|
|
||||||
#else // ENABLE_WALLET
|
#else // ENABLE_WALLET
|
||||||
LogPrintf("No wallet support compiled in!\n");
|
LogPrintf("No wallet support compiled in!\n");
|
||||||
#endif // !ENABLE_WALLET
|
#endif // !ENABLE_WALLET
|
||||||
|
|
|
@ -18,7 +18,6 @@ namespace boost
|
||||||
class thread_group;
|
class thread_group;
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
extern CWallet* pwalletMain;
|
|
||||||
extern ZCJoinSplit* pzcashParams;
|
extern ZCJoinSplit* pzcashParams;
|
||||||
|
|
||||||
void StartShutdown();
|
void StartShutdown();
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
#include "txmempool.h"
|
#include "txmempool.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "validationinterface.h"
|
#include "validationinterface.h"
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
#include "wallet/wallet.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||||
|
|
||||||
#include "wallet_ismine.h"
|
#include "ismine.h"
|
||||||
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "keystore.h"
|
#include "keystore.h"
|
|
@ -3,8 +3,8 @@
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||||
|
|
||||||
#ifndef BITCOIN_WALLET_WALLET_ISMINE_H
|
#ifndef BITCOIN_SCRIPT_ISMINE_H
|
||||||
#define BITCOIN_WALLET_WALLET_ISMINE_H
|
#define BITCOIN_SCRIPT_ISMINE_H
|
||||||
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "script/standard.h"
|
#include "script/standard.h"
|
||||||
|
@ -30,4 +30,4 @@ typedef uint8_t isminefilter;
|
||||||
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
|
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
|
||||||
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
|
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
|
||||||
|
|
||||||
#endif // BITCOIN_WALLET_WALLET_ISMINE_H
|
#endif // BITCOIN_SCRIPT_ISMINE_H
|
|
@ -10,12 +10,10 @@
|
||||||
#include "script/script_error.h"
|
#include "script/script_error.h"
|
||||||
#include "script/interpreter.h"
|
#include "script/interpreter.h"
|
||||||
#include "script/sign.h"
|
#include "script/sign.h"
|
||||||
|
#include "script/ismine.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
#include "wallet/wallet_ismine.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
@ -215,10 +213,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
||||||
CTxDestination addr;
|
CTxDestination addr;
|
||||||
BOOST_CHECK(ExtractDestination(s, addr));
|
BOOST_CHECK(ExtractDestination(s, addr));
|
||||||
BOOST_CHECK(addr == keyaddr[0]);
|
BOOST_CHECK(addr == keyaddr[0]);
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
BOOST_CHECK(IsMine(keystore, s));
|
BOOST_CHECK(IsMine(keystore, s));
|
||||||
BOOST_CHECK(!IsMine(emptykeystore, s));
|
BOOST_CHECK(!IsMine(emptykeystore, s));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
vector<valtype> solutions;
|
vector<valtype> solutions;
|
||||||
|
@ -230,10 +226,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
||||||
CTxDestination addr;
|
CTxDestination addr;
|
||||||
BOOST_CHECK(ExtractDestination(s, addr));
|
BOOST_CHECK(ExtractDestination(s, addr));
|
||||||
BOOST_CHECK(addr == keyaddr[0]);
|
BOOST_CHECK(addr == keyaddr[0]);
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
BOOST_CHECK(IsMine(keystore, s));
|
BOOST_CHECK(IsMine(keystore, s));
|
||||||
BOOST_CHECK(!IsMine(emptykeystore, s));
|
BOOST_CHECK(!IsMine(emptykeystore, s));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
vector<valtype> solutions;
|
vector<valtype> solutions;
|
||||||
|
@ -244,11 +238,9 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
||||||
BOOST_CHECK_EQUAL(solutions.size(), 4U);
|
BOOST_CHECK_EQUAL(solutions.size(), 4U);
|
||||||
CTxDestination addr;
|
CTxDestination addr;
|
||||||
BOOST_CHECK(!ExtractDestination(s, addr));
|
BOOST_CHECK(!ExtractDestination(s, addr));
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
BOOST_CHECK(IsMine(keystore, s));
|
BOOST_CHECK(IsMine(keystore, s));
|
||||||
BOOST_CHECK(!IsMine(emptykeystore, s));
|
BOOST_CHECK(!IsMine(emptykeystore, s));
|
||||||
BOOST_CHECK(!IsMine(partialkeystore, s));
|
BOOST_CHECK(!IsMine(partialkeystore, s));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
vector<valtype> solutions;
|
vector<valtype> solutions;
|
||||||
|
@ -263,11 +255,9 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
||||||
BOOST_CHECK(addrs[0] == keyaddr[0]);
|
BOOST_CHECK(addrs[0] == keyaddr[0]);
|
||||||
BOOST_CHECK(addrs[1] == keyaddr[1]);
|
BOOST_CHECK(addrs[1] == keyaddr[1]);
|
||||||
BOOST_CHECK(nRequired == 1);
|
BOOST_CHECK(nRequired == 1);
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
BOOST_CHECK(IsMine(keystore, s));
|
BOOST_CHECK(IsMine(keystore, s));
|
||||||
BOOST_CHECK(!IsMine(emptykeystore, s));
|
BOOST_CHECK(!IsMine(emptykeystore, s));
|
||||||
BOOST_CHECK(!IsMine(partialkeystore, s));
|
BOOST_CHECK(!IsMine(partialkeystore, s));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
vector<valtype> solutions;
|
vector<valtype> solutions;
|
||||||
|
|
|
@ -11,12 +11,9 @@
|
||||||
#include "script/script.h"
|
#include "script/script.h"
|
||||||
#include "script/script_error.h"
|
#include "script/script_error.h"
|
||||||
#include "script/sign.h"
|
#include "script/sign.h"
|
||||||
|
#include "script/ismine.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
#include "wallet/wallet_ismine.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
@ -106,9 +103,7 @@ BOOST_DATA_TEST_CASE(sign, boost::unit_test::data::xrange(static_cast<int>(Conse
|
||||||
txTo[i].vin[0].prevout.n = i;
|
txTo[i].vin[0].prevout.n = i;
|
||||||
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
||||||
txTo[i].vout[0].nValue = 1;
|
txTo[i].vout[0].nValue = 1;
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
|
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
|
@ -210,9 +205,7 @@ BOOST_DATA_TEST_CASE(set, boost::unit_test::data::xrange(static_cast<int>(Consen
|
||||||
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
||||||
txTo[i].vout[0].nValue = 1*CENT;
|
txTo[i].vout[0].nValue = 1*CENT;
|
||||||
txTo[i].vout[0].scriptPubKey = inner[i];
|
txTo[i].vout[0].scriptPubKey = inner[i];
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
|
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,11 +24,6 @@
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "rpc/server.h"
|
#include "rpc/server.h"
|
||||||
#include "rpc/register.h"
|
#include "rpc/register.h"
|
||||||
#include "util.h"
|
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
#include "wallet/db.h"
|
|
||||||
#include "wallet/wallet.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
@ -37,7 +32,6 @@
|
||||||
#include "librustzcash.h"
|
#include "librustzcash.h"
|
||||||
|
|
||||||
CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h
|
CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h
|
||||||
CWallet* pwalletMain;
|
|
||||||
ZCJoinSplit *pzcashParams;
|
ZCJoinSplit *pzcashParams;
|
||||||
|
|
||||||
extern bool fPrintToConsole;
|
extern bool fPrintToConsole;
|
||||||
|
@ -99,10 +93,6 @@ TestingSetup::TestingSetup(const std::string& chainName) : JoinSplitTestingSetup
|
||||||
// Ideally we'd move all the RPC tests to the functional testing framework
|
// Ideally we'd move all the RPC tests to the functional testing framework
|
||||||
// instead of unit tests, but for now we need these here.
|
// instead of unit tests, but for now we need these here.
|
||||||
RegisterAllCoreRPCCommands(tableRPC);
|
RegisterAllCoreRPCCommands(tableRPC);
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
bitdb.MakeMock();
|
|
||||||
RegisterWalletRPCCommands(tableRPC);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Save current path, in case a test changes it
|
// Save current path, in case a test changes it
|
||||||
orig_current_path = boost::filesystem::current_path();
|
orig_current_path = boost::filesystem::current_path();
|
||||||
|
@ -115,12 +105,6 @@ TestingSetup::TestingSetup(const std::string& chainName) : JoinSplitTestingSetup
|
||||||
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
|
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
|
||||||
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
|
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
|
||||||
InitBlockIndex(chainparams);
|
InitBlockIndex(chainparams);
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
bool fFirstRun;
|
|
||||||
pwalletMain = new CWallet("wallet.dat");
|
|
||||||
pwalletMain->LoadWallet(fFirstRun);
|
|
||||||
RegisterValidationInterface(pwalletMain);
|
|
||||||
#endif
|
|
||||||
nScriptCheckThreads = 3;
|
nScriptCheckThreads = 3;
|
||||||
for (int i=0; i < nScriptCheckThreads-1; i++)
|
for (int i=0; i < nScriptCheckThreads-1; i++)
|
||||||
threadGroup.create_thread(&ThreadScriptCheck);
|
threadGroup.create_thread(&ThreadScriptCheck);
|
||||||
|
@ -132,19 +116,10 @@ TestingSetup::~TestingSetup()
|
||||||
UnregisterNodeSignals(GetNodeSignals());
|
UnregisterNodeSignals(GetNodeSignals());
|
||||||
threadGroup.interrupt_all();
|
threadGroup.interrupt_all();
|
||||||
threadGroup.join_all();
|
threadGroup.join_all();
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
UnregisterValidationInterface(pwalletMain);
|
|
||||||
delete pwalletMain;
|
|
||||||
pwalletMain = NULL;
|
|
||||||
#endif
|
|
||||||
UnloadBlockIndex();
|
UnloadBlockIndex();
|
||||||
delete pcoinsTip;
|
delete pcoinsTip;
|
||||||
delete pcoinsdbview;
|
delete pcoinsdbview;
|
||||||
delete pblocktree;
|
delete pblocktree;
|
||||||
#ifdef ENABLE_WALLET
|
|
||||||
bitdb.Flush(true);
|
|
||||||
bitdb.Reset();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Restore the previous current path so temporary directory can be deleted
|
// Restore the previous current path so temporary directory can be deleted
|
||||||
boost::filesystem::current_path(orig_current_path);
|
boost::filesystem::current_path(orig_current_path);
|
||||||
|
|
|
@ -27,8 +27,7 @@ struct JoinSplitTestingSetup: public BasicTestingSetup {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Testing setup that configures a complete environment.
|
/** Testing setup that configures a complete environment.
|
||||||
* Included are data directory, coins database, script check threads
|
* Included are data directory, coins database, script check threads setup.
|
||||||
* and wallet (if enabled) setup.
|
|
||||||
*/
|
*/
|
||||||
struct TestingSetup: public JoinSplitTestingSetup {
|
struct TestingSetup: public JoinSplitTestingSetup {
|
||||||
CCoinsViewDB *pcoinsdbview;
|
CCoinsViewDB *pcoinsdbview;
|
||||||
|
|
|
@ -405,7 +405,7 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
throw JSONRPCError(RPC_WALLET_ERROR, strError);
|
||||||
}
|
}
|
||||||
if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
|
if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of the wallet and coins were spent in the copy but not marked as spent here.");
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue sendtoaddress(const UniValue& params, bool fHelp)
|
UniValue sendtoaddress(const UniValue& params, bool fHelp)
|
||||||
|
@ -1806,7 +1806,7 @@ UniValue backupwallet(const UniValue& params, bool fHelp)
|
||||||
if (fHelp || params.size() != 1)
|
if (fHelp || params.size() != 1)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"backupwallet \"destination\"\n"
|
"backupwallet \"destination\"\n"
|
||||||
"\nSafely copies wallet.dat to destination filename\n"
|
"\nSafely copies current wallet file to destination filename\n"
|
||||||
"\nArguments:\n"
|
"\nArguments:\n"
|
||||||
"1. \"destination\" (string, required) The destination filename, saved in the directory set by -exportdir option.\n"
|
"1. \"destination\" (string, required) The destination filename, saved in the directory set by -exportdir option.\n"
|
||||||
"\nResult:\n"
|
"\nResult:\n"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
#include "wallet/walletdb.h"
|
#include "wallet/walletdb.h"
|
||||||
|
|
||||||
#include "test/test_bitcoin.h"
|
#include "wallet/test/wallet_test_fixture.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
extern CWallet* pwalletMain;
|
extern CWallet* pwalletMain;
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(accounting_tests, TestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
GetResults(CWalletDB& walletdb, std::map<CAmount, CAccountingEntry>& results)
|
GetResults(CWalletDB& walletdb, std::map<CAmount, CAccountingEntry>& results)
|
|
@ -9,7 +9,7 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
|
|
||||||
#include "test/test_bitcoin.h"
|
#include "wallet/test/wallet_test_fixture.h"
|
||||||
|
|
||||||
#include "zcash/Address.hpp"
|
#include "zcash/Address.hpp"
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ static UniValue ValueFromString(const std::string &str)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, TestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, WalletTestingSetup)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(rpc_addmultisig)
|
BOOST_AUTO_TEST_CASE(rpc_addmultisig)
|
||||||
{
|
{
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "wallet/test/wallet_test_fixture.h"
|
||||||
|
|
||||||
|
#include "rpc/server.h"
|
||||||
|
#include "wallet/db.h"
|
||||||
|
#include "wallet/wallet.h"
|
||||||
|
|
||||||
|
WalletTestingSetup::WalletTestingSetup(): TestingSetup()
|
||||||
|
{
|
||||||
|
bitdb.MakeMock();
|
||||||
|
|
||||||
|
bool fFirstRun;
|
||||||
|
pwalletMain = new CWallet("wallet_test.dat");
|
||||||
|
pwalletMain->LoadWallet(fFirstRun);
|
||||||
|
RegisterValidationInterface(pwalletMain);
|
||||||
|
|
||||||
|
RegisterWalletRPCCommands(tableRPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletTestingSetup::~WalletTestingSetup()
|
||||||
|
{
|
||||||
|
UnregisterValidationInterface(pwalletMain);
|
||||||
|
delete pwalletMain;
|
||||||
|
pwalletMain = NULL;
|
||||||
|
|
||||||
|
bitdb.Flush(true);
|
||||||
|
bitdb.Reset();
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright (c) 2016 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_WALLET_TEST_FIXTURE_H
|
||||||
|
#define BITCOIN_WALLET_TEST_FIXTURE_H
|
||||||
|
|
||||||
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
|
/** Testing setup and teardown for wallet.
|
||||||
|
*/
|
||||||
|
struct WalletTestingSetup: public TestingSetup {
|
||||||
|
WalletTestingSetup();
|
||||||
|
~WalletTestingSetup();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "test/test_bitcoin.h"
|
#include "wallet/test/wallet_test_fixture.h"
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
@ -25,7 +25,7 @@ using namespace std;
|
||||||
|
|
||||||
typedef set<pair<const CWalletTx*,unsigned int> > CoinSet;
|
typedef set<pair<const CWalletTx*,unsigned int> > CoinSet;
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(wallet_tests, TestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
|
||||||
|
|
||||||
static CWallet wallet;
|
static CWallet wallet;
|
||||||
static vector<COutput> vCoins;
|
static vector<COutput> vCoins;
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace libzcash;
|
using namespace libzcash;
|
||||||
|
|
||||||
|
CWallet* pwalletMain = NULL;
|
||||||
/** Transaction fee set by the user */
|
/** Transaction fee set by the user */
|
||||||
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
|
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
|
||||||
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
|
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
|
||||||
|
@ -44,6 +45,8 @@ bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE;
|
||||||
bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS;
|
bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS;
|
||||||
bool fPayAtLeastCustomFee = true;
|
bool fPayAtLeastCustomFee = true;
|
||||||
|
|
||||||
|
const char * DEFAULT_WALLET_DAT = "wallet.dat";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
|
* Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
|
||||||
* Override with -mintxfee
|
* Override with -mintxfee
|
||||||
|
@ -816,8 +819,33 @@ void CWallet::Flush(bool shutdown)
|
||||||
bitdb.Flush(shutdown);
|
bitdb.Flush(shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString)
|
bool static UIError(const std::string &str)
|
||||||
{
|
{
|
||||||
|
uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void static UIWarning(const std::string &str)
|
||||||
|
{
|
||||||
|
uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string AmountErrMsg(const char * const optname, const std::string& strValue)
|
||||||
|
{
|
||||||
|
return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::Verify()
|
||||||
|
{
|
||||||
|
std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
|
||||||
|
|
||||||
|
LogPrintf("Using wallet %s\n", walletFile);
|
||||||
|
uiInterface.InitMessage(_("Verifying wallet..."));
|
||||||
|
|
||||||
|
// Wallet file must be a plain filename without a directory
|
||||||
|
if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile))
|
||||||
|
return UIError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string()));
|
||||||
|
|
||||||
if (!bitdb.Open(GetDataDir()))
|
if (!bitdb.Open(GetDataDir()))
|
||||||
{
|
{
|
||||||
// try moving the database env out of the way
|
// try moving the database env out of the way
|
||||||
|
@ -833,9 +861,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er
|
||||||
// try again
|
// try again
|
||||||
if (!bitdb.Open(GetDataDir())) {
|
if (!bitdb.Open(GetDataDir())) {
|
||||||
// if it still fails, it probably means we can't even create the database env
|
// if it still fails, it probably means we can't even create the database env
|
||||||
string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir());
|
return UIError(strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()));
|
||||||
errorString += msg;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,13 +877,14 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er
|
||||||
CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover);
|
CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover);
|
||||||
if (r == CDBEnv::RECOVER_OK)
|
if (r == CDBEnv::RECOVER_OK)
|
||||||
{
|
{
|
||||||
warningString += strprintf(_("Warning: wallet.dat corrupt, data salvaged!"
|
UIWarning(strprintf(_("Warning: Wallet file corrupt, data salvaged!"
|
||||||
" Original wallet.dat saved as wallet.{timestamp}.bak in %s; if"
|
" Original %s saved as %s in %s; if"
|
||||||
" your balance or transactions are incorrect you should"
|
" your balance or transactions are incorrect you should"
|
||||||
" restore from a backup."), GetDataDir());
|
" restore from a backup."),
|
||||||
|
walletFile, "wallet.{timestamp}.bak", GetDataDir()));
|
||||||
}
|
}
|
||||||
if (r == CDBEnv::RECOVER_FAIL)
|
if (r == CDBEnv::RECOVER_FAIL)
|
||||||
errorString += _("wallet.dat corrupt, salvage failed");
|
return UIError(strprintf(_("%s corrupt, salvage failed"), walletFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -4363,6 +4390,268 @@ bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, st
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CWallet::GetWalletHelpString(bool showDebug)
|
||||||
|
{
|
||||||
|
std::string strUsage = HelpMessageGroup(_("Wallet options:"));
|
||||||
|
strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
|
||||||
|
strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
|
||||||
|
strUsage += HelpMessageOpt("-migration", _("Enable the Sprout to Sapling migration"));
|
||||||
|
strUsage += HelpMessageOpt("-migrationdestaddress=<zaddr>", _("Set the Sapling migration address"));
|
||||||
|
strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
|
||||||
|
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
|
||||||
|
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
|
||||||
|
CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
|
||||||
|
strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions on startup"));
|
||||||
|
strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet on startup"));
|
||||||
|
strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS));
|
||||||
|
strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
|
||||||
|
strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
|
||||||
|
strUsage += HelpMessageOpt("-txexpirydelta", strprintf(_("Set the number of blocks after which a transaction that has not been mined will become invalid (min: %u, default: %u (pre-Blossom) or %u (post-Blossom))"), TX_EXPIRING_SOON_THRESHOLD + 1, DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA));
|
||||||
|
strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup"));
|
||||||
|
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
|
||||||
|
strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST));
|
||||||
|
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
|
||||||
|
strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
|
||||||
|
" " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
|
||||||
|
|
||||||
|
if (showDebug)
|
||||||
|
{
|
||||||
|
strUsage += HelpMessageGroup(_("Wallet debugging/testing options:"));
|
||||||
|
|
||||||
|
strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
|
||||||
|
strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET));
|
||||||
|
strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB));
|
||||||
|
}
|
||||||
|
|
||||||
|
return strUsage;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::InitLoadWallet(bool clearWitnessCaches)
|
||||||
|
{
|
||||||
|
std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
|
||||||
|
|
||||||
|
// needed to restore wallet transaction meta data after -zapwallettxes
|
||||||
|
std::vector<CWalletTx> vWtx;
|
||||||
|
|
||||||
|
if (GetBoolArg("-zapwallettxes", false)) {
|
||||||
|
uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
|
||||||
|
|
||||||
|
CWallet *tempWallet = new CWallet(walletFile);
|
||||||
|
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
|
||||||
|
if (nZapWalletRet != DB_LOAD_OK) {
|
||||||
|
return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete tempWallet;
|
||||||
|
tempWallet = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uiInterface.InitMessage(_("Loading wallet..."));
|
||||||
|
|
||||||
|
int64_t nStart = GetTimeMillis();
|
||||||
|
bool fFirstRun = true;
|
||||||
|
CWallet *walletInstance = new CWallet(walletFile);
|
||||||
|
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
|
||||||
|
if (nLoadWalletRet != DB_LOAD_OK)
|
||||||
|
{
|
||||||
|
if (nLoadWalletRet == DB_CORRUPT)
|
||||||
|
return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
|
||||||
|
else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
|
||||||
|
{
|
||||||
|
UIWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
|
||||||
|
" or address book entries might be missing or incorrect."),
|
||||||
|
walletFile));
|
||||||
|
}
|
||||||
|
else if (nLoadWalletRet == DB_TOO_NEW)
|
||||||
|
return UIError(strprintf(_("Error loading %s: Wallet requires newer version of %s"),
|
||||||
|
walletFile, _(PACKAGE_NAME)));
|
||||||
|
else if (nLoadWalletRet == DB_NEED_REWRITE)
|
||||||
|
{
|
||||||
|
return UIError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return UIError(strprintf(_("Error loading %s"), walletFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetBoolArg("-upgradewallet", fFirstRun))
|
||||||
|
{
|
||||||
|
int nMaxVersion = GetArg("-upgradewallet", 0);
|
||||||
|
if (nMaxVersion == 0) // the -upgradewallet without argument case
|
||||||
|
{
|
||||||
|
LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
|
||||||
|
nMaxVersion = CLIENT_VERSION;
|
||||||
|
walletInstance->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
|
||||||
|
if (nMaxVersion < walletInstance->GetVersion())
|
||||||
|
{
|
||||||
|
return UIError(_("Cannot downgrade wallet"));
|
||||||
|
}
|
||||||
|
walletInstance->SetMaxVersion(nMaxVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!walletInstance->HaveHDSeed())
|
||||||
|
{
|
||||||
|
// We can't set the new HD seed until the wallet is decrypted.
|
||||||
|
// https://github.com/zcash/zcash/issues/3607
|
||||||
|
if (!walletInstance->IsCrypted()) {
|
||||||
|
// generate a new HD seed
|
||||||
|
walletInstance->GenerateNewSeed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sapling migration status
|
||||||
|
walletInstance->fSaplingMigrationEnabled = GetBoolArg("-migration", false);
|
||||||
|
|
||||||
|
if (fFirstRun)
|
||||||
|
{
|
||||||
|
// Create new keyUser and set as default key
|
||||||
|
CPubKey newDefaultKey;
|
||||||
|
if (walletInstance->GetKeyFromPool(newDefaultKey)) {
|
||||||
|
walletInstance->SetDefaultKey(newDefaultKey);
|
||||||
|
if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive"))
|
||||||
|
return UIError(_("Cannot write default address") += "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
walletInstance->SetBestChain(chainActive.GetLocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart);
|
||||||
|
|
||||||
|
RegisterValidationInterface(walletInstance);
|
||||||
|
|
||||||
|
CBlockIndex *pindexRescan = chainActive.Tip();
|
||||||
|
if (clearWitnessCaches || GetBoolArg("-rescan", false))
|
||||||
|
{
|
||||||
|
walletInstance->ClearNoteWitnessCache();
|
||||||
|
pindexRescan = chainActive.Genesis();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CWalletDB walletdb(walletFile);
|
||||||
|
CBlockLocator locator;
|
||||||
|
if (walletdb.ReadBestBlock(locator))
|
||||||
|
pindexRescan = FindForkInGlobalIndex(chainActive, locator);
|
||||||
|
else
|
||||||
|
pindexRescan = chainActive.Genesis();
|
||||||
|
}
|
||||||
|
if (chainActive.Tip() && chainActive.Tip() != pindexRescan)
|
||||||
|
{
|
||||||
|
// We can't rescan beyond non-pruned blocks, stop and throw an error.
|
||||||
|
// This might happen if a user uses a old wallet within a pruned node,
|
||||||
|
// or if they ran -disablewallet for a longer time, then decided to re-enable.
|
||||||
|
if (fPruneMode)
|
||||||
|
{
|
||||||
|
CBlockIndex *block = chainActive.Tip();
|
||||||
|
while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block)
|
||||||
|
block = block->pprev;
|
||||||
|
|
||||||
|
if (pindexRescan != block)
|
||||||
|
return UIError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
uiInterface.InitMessage(_("Rescanning..."));
|
||||||
|
LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
|
||||||
|
nStart = GetTimeMillis();
|
||||||
|
walletInstance->ScanForWalletTransactions(pindexRescan, true);
|
||||||
|
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
|
||||||
|
walletInstance->SetBestChain(chainActive.GetLocator());
|
||||||
|
nWalletDBUpdated++;
|
||||||
|
|
||||||
|
// Restore wallet transaction metadata after -zapwallettxes=1
|
||||||
|
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
|
||||||
|
{
|
||||||
|
CWalletDB walletdb(walletFile);
|
||||||
|
|
||||||
|
BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
|
||||||
|
{
|
||||||
|
uint256 hash = wtxOld.GetHash();
|
||||||
|
std::map<uint256, CWalletTx>::iterator mi = walletInstance->mapWallet.find(hash);
|
||||||
|
if (mi != walletInstance->mapWallet.end())
|
||||||
|
{
|
||||||
|
const CWalletTx* copyFrom = &wtxOld;
|
||||||
|
CWalletTx* copyTo = &mi->second;
|
||||||
|
copyTo->mapValue = copyFrom->mapValue;
|
||||||
|
copyTo->vOrderForm = copyFrom->vOrderForm;
|
||||||
|
copyTo->nTimeReceived = copyFrom->nTimeReceived;
|
||||||
|
copyTo->nTimeSmart = copyFrom->nTimeSmart;
|
||||||
|
copyTo->fFromMe = copyFrom->fFromMe;
|
||||||
|
copyTo->strFromAccount = copyFrom->strFromAccount;
|
||||||
|
copyTo->nOrderPos = copyFrom->nOrderPos;
|
||||||
|
copyTo->WriteToDisk(&walletdb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
walletInstance->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
|
||||||
|
|
||||||
|
pwalletMain = walletInstance;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWallet::ParameterInteraction()
|
||||||
|
{
|
||||||
|
if (mapArgs.count("-mintxfee"))
|
||||||
|
{
|
||||||
|
CAmount n = 0;
|
||||||
|
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
|
||||||
|
CWallet::minTxFee = CFeeRate(n);
|
||||||
|
else
|
||||||
|
return UIError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"]));
|
||||||
|
}
|
||||||
|
if (mapArgs.count("-paytxfee"))
|
||||||
|
{
|
||||||
|
CAmount nFeePerK = 0;
|
||||||
|
if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
|
||||||
|
return UIError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"]));
|
||||||
|
if (nFeePerK > HIGH_TX_FEE_PER_KB)
|
||||||
|
UIWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
|
||||||
|
payTxFee = CFeeRate(nFeePerK, 1000);
|
||||||
|
if (payTxFee < ::minRelayTxFee)
|
||||||
|
{
|
||||||
|
return UIError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
|
||||||
|
mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mapArgs.count("-maxtxfee"))
|
||||||
|
{
|
||||||
|
CAmount nMaxFee = 0;
|
||||||
|
if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee))
|
||||||
|
return UIError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"]));
|
||||||
|
if (nMaxFee > HIGH_MAX_TX_FEE)
|
||||||
|
UIWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
|
||||||
|
maxTxFee = nMaxFee;
|
||||||
|
if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
|
||||||
|
{
|
||||||
|
return UIError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
|
||||||
|
mapArgs["-maxtxfee"], ::minRelayTxFee.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
|
||||||
|
if (mapArgs.count("-txexpirydelta")) {
|
||||||
|
int64_t expiryDelta = atoi64(mapArgs["-txexpirydelta"]);
|
||||||
|
uint32_t minExpiryDelta = TX_EXPIRING_SOON_THRESHOLD + 1;
|
||||||
|
if (expiryDelta < minExpiryDelta) {
|
||||||
|
return UIError(strprintf(_("Invalid value for -txexpirydelta='%u' (must be least %u)"), expiryDelta, minExpiryDelta));
|
||||||
|
}
|
||||||
|
expiryDeltaArg = expiryDelta;
|
||||||
|
}
|
||||||
|
bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
|
||||||
|
fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS);
|
||||||
|
|
||||||
|
// Check Sapling migration address if set and is a valid Sapling address
|
||||||
|
if (mapArgs.count("-migrationdestaddress")) {
|
||||||
|
std::string migrationDestAddress = mapArgs["-migrationdestaddress"];
|
||||||
|
libzcash::PaymentAddress address = DecodePaymentAddress(migrationDestAddress);
|
||||||
|
if (boost::get<libzcash::SaplingPaymentAddress>(&address) == nullptr) {
|
||||||
|
return UIError(_("-migrationdestaddress must be a valid Sapling address."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
CKeyPool::CKeyPool()
|
CKeyPool::CKeyPool()
|
||||||
{
|
{
|
||||||
nTime = GetTime();
|
nTime = GetTime();
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "utilstrencodings.h"
|
||||||
#include "validationinterface.h"
|
#include "validationinterface.h"
|
||||||
|
#include "script/ismine.h"
|
||||||
#include "wallet/crypter.h"
|
#include "wallet/crypter.h"
|
||||||
#include "wallet/wallet_ismine.h"
|
|
||||||
#include "wallet/walletdb.h"
|
#include "wallet/walletdb.h"
|
||||||
#include "wallet/rpcwallet.h"
|
#include "wallet/rpcwallet.h"
|
||||||
#include "zcash/Address.hpp"
|
#include "zcash/Address.hpp"
|
||||||
|
@ -38,6 +38,8 @@
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
extern CWallet* pwalletMain;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings
|
* Settings
|
||||||
*/
|
*/
|
||||||
|
@ -71,6 +73,8 @@ static const unsigned int WITNESS_CACHE_SIZE = MAX_REORG_LENGTH + 1;
|
||||||
//! Size of HD seed in bytes
|
//! Size of HD seed in bytes
|
||||||
static const size_t HD_WALLET_SEED_LENGTH = 32;
|
static const size_t HD_WALLET_SEED_LENGTH = 32;
|
||||||
|
|
||||||
|
extern const char * DEFAULT_WALLET_DAT;
|
||||||
|
|
||||||
class CBlockIndex;
|
class CBlockIndex;
|
||||||
class CCoinControl;
|
class CCoinControl;
|
||||||
class COutput;
|
class COutput;
|
||||||
|
@ -1289,7 +1293,7 @@ public:
|
||||||
void Flush(bool shutdown=false);
|
void Flush(bool shutdown=false);
|
||||||
|
|
||||||
//! Verify the wallet database and perform salvage if required
|
//! Verify the wallet database and perform salvage if required
|
||||||
static bool Verify(const std::string& walletFile, std::string& warningString, std::string& errorString);
|
static bool Verify();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Address book entry changed.
|
* Address book entry changed.
|
||||||
|
@ -1360,6 +1364,15 @@ public:
|
||||||
bool ignoreSpent=true,
|
bool ignoreSpent=true,
|
||||||
bool requireSpendingKey=true,
|
bool requireSpendingKey=true,
|
||||||
bool ignoreLocked=true);
|
bool ignoreLocked=true);
|
||||||
|
|
||||||
|
/* Returns the wallets help message */
|
||||||
|
static std::string GetWalletHelpString(bool showDebug);
|
||||||
|
|
||||||
|
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
|
||||||
|
static bool InitLoadWallet(bool clearWitnessCaches);
|
||||||
|
|
||||||
|
/* Wallets parameter interaction */
|
||||||
|
static bool ParameterInteraction();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A key allocated from the key pool. */
|
/** A key allocated from the key pool. */
|
||||||
|
|
|
@ -1108,16 +1108,16 @@ void ThreadFlushWalletDB(const string& strFile)
|
||||||
map<string, int>::iterator mi = bitdb.mapFileUseCount.find(strFile);
|
map<string, int>::iterator mi = bitdb.mapFileUseCount.find(strFile);
|
||||||
if (mi != bitdb.mapFileUseCount.end())
|
if (mi != bitdb.mapFileUseCount.end())
|
||||||
{
|
{
|
||||||
LogPrint("db", "Flushing wallet.dat\n");
|
LogPrint("db", "Flushing %s\n", strFile);
|
||||||
nLastFlushed = nWalletDBUpdated;
|
nLastFlushed = nWalletDBUpdated;
|
||||||
int64_t nStart = GetTimeMillis();
|
int64_t nStart = GetTimeMillis();
|
||||||
|
|
||||||
// Flush wallet.dat so it's self contained
|
// Flush wallet file so it's self contained
|
||||||
bitdb.CloseDb(strFile);
|
bitdb.CloseDb(strFile);
|
||||||
bitdb.CheckpointLSN(strFile);
|
bitdb.CheckpointLSN(strFile);
|
||||||
|
|
||||||
bitdb.mapFileUseCount.erase(mi++);
|
bitdb.mapFileUseCount.erase(mi++);
|
||||||
LogPrint("db", "Flushed wallet.dat %dms\n", GetTimeMillis() - nStart);
|
LogPrint("db", "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1140,7 +1140,7 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
|
||||||
bitdb.CheckpointLSN(wallet.strWalletFile);
|
bitdb.CheckpointLSN(wallet.strWalletFile);
|
||||||
bitdb.mapFileUseCount.erase(wallet.strWalletFile);
|
bitdb.mapFileUseCount.erase(wallet.strWalletFile);
|
||||||
|
|
||||||
// Copy wallet.dat
|
// Copy wallet file
|
||||||
boost::filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
|
boost::filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
|
||||||
boost::filesystem::path pathDest(strDest);
|
boost::filesystem::path pathDest(strDest);
|
||||||
if (boost::filesystem::is_directory(pathDest))
|
if (boost::filesystem::is_directory(pathDest))
|
||||||
|
@ -1148,10 +1148,10 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists);
|
boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists);
|
||||||
LogPrintf("copied wallet.dat to %s\n", pathDest.string());
|
LogPrintf("copied %s to %s\n", wallet.strWalletFile, pathDest.string());
|
||||||
return true;
|
return true;
|
||||||
} catch (const boost::filesystem::filesystem_error& e) {
|
} catch (const boost::filesystem::filesystem_error& e) {
|
||||||
LogPrintf("error copying wallet.dat to %s - %s\n", pathDest.string(), e.what());
|
LogPrintf("error copying %s to %s - %s\n", wallet.strWalletFile, pathDest.string(), e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1162,15 +1162,15 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Try to (very carefully!) recover wallet.dat if there is a problem.
|
// Try to (very carefully!) recover wallet file if there is a problem.
|
||||||
//
|
//
|
||||||
bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys)
|
bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys)
|
||||||
{
|
{
|
||||||
// Recovery procedure:
|
// Recovery procedure:
|
||||||
// move wallet.dat to wallet.timestamp.bak
|
// move wallet file to wallet.timestamp.bak
|
||||||
// Call Salvage with fAggressive=true to
|
// Call Salvage with fAggressive=true to
|
||||||
// get as much data as possible.
|
// get as much data as possible.
|
||||||
// Rewrite salvaged data to wallet.dat
|
// Rewrite salvaged data to fresh wallet file
|
||||||
// Set -rescan so any missing transactions will be
|
// Set -rescan so any missing transactions will be
|
||||||
// found.
|
// found.
|
||||||
int64_t now = GetTime();
|
int64_t now = GetTime();
|
||||||
|
|
|
@ -119,7 +119,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Access to the wallet database (wallet.dat) */
|
/** Access to the wallet database */
|
||||||
class CWalletDB : public CDB
|
class CWalletDB : public CDB
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in New Issue