diff options
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/crypter.cpp | 3 | ||||
-rw-r--r-- | src/wallet/crypter.h | 1 | ||||
-rw-r--r-- | src/wallet/db.cpp | 6 | ||||
-rw-r--r-- | src/wallet/db.h | 4 | ||||
-rw-r--r-- | src/wallet/feebumper.cpp | 92 | ||||
-rw-r--r-- | src/wallet/feebumper.h | 8 | ||||
-rw-r--r-- | src/wallet/fees.cpp | 1 | ||||
-rw-r--r-- | src/wallet/init.cpp | 3 | ||||
-rw-r--r-- | src/wallet/ismine.cpp | 1 | ||||
-rw-r--r-- | src/wallet/load.cpp | 13 | ||||
-rw-r--r-- | src/wallet/psbtwallet.h | 2 | ||||
-rw-r--r-- | src/wallet/rpcdump.cpp | 1 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 43 | ||||
-rw-r--r-- | src/wallet/test/wallet_tests.cpp | 4 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 188 | ||||
-rw-r--r-- | src/wallet/wallet.h | 22 | ||||
-rw-r--r-- | src/wallet/walletdb.cpp | 9 | ||||
-rw-r--r-- | src/wallet/walletdb.h | 5 | ||||
-rw-r--r-- | src/wallet/wallettool.h | 1 |
19 files changed, 171 insertions, 236 deletions
diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 0b76c1a0eb..f6179aa298 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -6,11 +6,8 @@ #include <crypto/aes.h> #include <crypto/sha512.h> -#include <script/script.h> -#include <script/standard.h> #include <util/system.h> -#include <string> #include <vector> int CCrypter::BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 17a4e9820c..4367a5047f 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -9,7 +9,6 @@ #include <support/allocators/secure.h> #include <script/signingprovider.h> -#include <atomic> const unsigned int WALLET_CRYPTO_KEY_SIZE = 32; const unsigned int WALLET_CRYPTO_SALT_SIZE = 8; diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 26aeb754ad..e48eee6c2c 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -412,7 +412,7 @@ bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, std::string& er return true; } -bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc) +bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::vector<std::string>& warnings, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc) { std::string walletFile; std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, walletFile); @@ -424,11 +424,11 @@ bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::string& w BerkeleyEnvironment::VerifyResult r = env->Verify(walletFile, recoverFunc, backup_filename); if (r == BerkeleyEnvironment::VerifyResult::RECOVER_OK) { - warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!" + warnings.push_back(strprintf(_("Warning: Wallet file corrupt, data salvaged!" " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup.").translated, - walletFile, backup_filename, walletDir); + walletFile, backup_filename, walletDir)); } if (r == BerkeleyEnvironment::VerifyResult::RECOVER_FAIL) { diff --git a/src/wallet/db.h b/src/wallet/db.h index 94f41eaf16..abec3ae4e2 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -10,9 +10,7 @@ #include <fs.h> #include <serialize.h> #include <streams.h> -#include <sync.h> #include <util/system.h> -#include <version.h> #include <atomic> #include <map> @@ -246,7 +244,7 @@ public: /* verifies the database environment */ static bool VerifyEnvironment(const fs::path& file_path, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc); + static bool VerifyDatabaseFile(const fs::path& file_path, std::vector<std::string>& warnings, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc); template <typename K, typename T> bool Read(const K& key, T& value) diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index b87231293f..0a4bb3f396 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <consensus/validation.h> #include <interfaces/chain.h> #include <wallet/coincontrol.h> #include <wallet/feebumper.h> @@ -17,15 +16,15 @@ //! Check whether transaction has descendant in wallet or mempool, or has been //! mined, or conflicts with a mined transaction. Return a feebumper::Result. -static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chain, const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet) +static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chain, const CWallet& wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) { - if (wallet->HasWalletSpend(wtx.GetHash())) { + if (wallet.HasWalletSpend(wtx.GetHash())) { errors.push_back("Transaction has descendants in the wallet"); return feebumper::Result::INVALID_PARAMETER; } { - if (wallet->chain().hasDescendantsInMempool(wtx.GetHash())) { + if (wallet.chain().hasDescendantsInMempool(wtx.GetHash())) { errors.push_back("Transaction has descendants in the mempool"); return feebumper::Result::INVALID_PARAMETER; } @@ -48,7 +47,7 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai // check that original tx consists entirely of our inputs // if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee) - if (!wallet->IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) { + if (!wallet.IsAllFromMe(*wtx.tx, ISMINE_SPENDABLE)) { errors.push_back("Transaction contains inputs that don't belong to this wallet"); return feebumper::Result::WALLET_ERROR; } @@ -58,13 +57,13 @@ static feebumper::Result PreconditionChecks(interfaces::Chain::Lock& locked_chai } //! Check if the user provided a valid feeRate -static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) { +static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<std::string>& errors) { // check that fee rate is higher than mempool's minimum fee // (no point in bumping fee if we know that the new tx won't be accepted to the mempool) // This may occur if the user set FeeRate, TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps, // in a rare situation where the mempool minimum fee increased significantly since the fee estimation just a // moment earlier. In this case, we report an error to the user, who may adjust the fee. - CFeeRate minMempoolFeeRate = wallet->chain().mempoolMinFee(); + CFeeRate minMempoolFeeRate = wallet.chain().mempoolMinFee(); if (newFeerate.GetFeePerK() < minMempoolFeeRate.GetFeePerK()) { errors.push_back(strprintf( @@ -76,7 +75,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt CAmount new_total_fee = newFeerate.GetFee(maxTxSize); - CFeeRate incrementalRelayFee = std::max(wallet->chain().relayIncrementalFee(), CFeeRate(WALLET_INCREMENTAL_RELAY_FEE)); + CFeeRate incrementalRelayFee = std::max(wallet.chain().relayIncrementalFee(), CFeeRate(WALLET_INCREMENTAL_RELAY_FEE)); // Given old total fee and transaction size, calculate the old feeRate CAmount old_fee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut(); @@ -91,7 +90,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt return feebumper::Result::INVALID_PARAMETER; } - CAmount requiredFee = GetRequiredFee(*wallet, maxTxSize); + CAmount requiredFee = GetRequiredFee(wallet, maxTxSize); if (new_total_fee < requiredFee) { errors.push_back(strprintf("Insufficient total fee (cannot be less than required fee %s)", FormatMoney(requiredFee))); @@ -99,7 +98,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt } // Check that in all cases the new fee doesn't violate maxTxFee - const CAmount max_tx_fee = wallet->m_default_max_tx_fee; + const CAmount max_tx_fee = wallet.m_default_max_tx_fee; if (new_total_fee > max_tx_fee) { errors.push_back(strprintf("Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)", FormatMoney(new_total_fee), FormatMoney(max_tx_fee))); @@ -109,7 +108,7 @@ static feebumper::Result CheckFeeRate(const CWallet* wallet, const CWalletTx& wt return feebumper::Result::OK; } -static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinControl& coin_control, CAmount& old_fee) +static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, CCoinControl& coin_control, CAmount& old_fee) { // Get the fee rate of the original transaction. This is calculated from // the tx fee/vsize, so it may have been rounded down. Add 1 satoshi to the @@ -123,15 +122,15 @@ static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinCont // the minimum of that and the wallet's conservative // WALLET_INCREMENTAL_RELAY_FEE value to future proof against changes to // network wide policy for incremental relay fee that our node may not be - // aware of. This ensures we're over the over the required relay fee rate + // aware of. This ensures we're over the required relay fee rate // (BIP 125 rule 4). The replacement tx will be at least as large as the // original tx, so the total fee will be greater (BIP 125 rule 3) - CFeeRate node_incremental_relay_fee = wallet->chain().relayIncrementalFee(); + CFeeRate node_incremental_relay_fee = wallet.chain().relayIncrementalFee(); CFeeRate wallet_incremental_relay_fee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE); feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee); // Fee rate must also be at least the wallet's GetMinimumFeeRate - CFeeRate min_feerate(GetMinimumFeeRate(*wallet, coin_control, /* feeCalc */ nullptr)); + CFeeRate min_feerate(GetMinimumFeeRate(wallet, coin_control, /* feeCalc */ nullptr)); // Set the required fee rate for the replacement transaction in coin control. return std::max(feerate, min_feerate); @@ -139,11 +138,11 @@ static CFeeRate EstimateFeeRate(CWallet* wallet, const CWalletTx& wtx, CCoinCont namespace feebumper { -bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid) +bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid) { - auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); - const CWalletTx* wtx = wallet->GetWalletTx(txid); + auto locked_chain = wallet.chain().lock(); + LOCK(wallet.cs_wallet); + const CWalletTx* wtx = wallet.GetWalletTx(txid); if (wtx == nullptr) return false; std::vector<std::string> errors_dummy; @@ -166,7 +165,7 @@ Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, co } const CWalletTx& wtx = it->second; - Result result = PreconditionChecks(*locked_chain, wallet, wtx, errors); + Result result = PreconditionChecks(*locked_chain, *wallet, wtx, errors); if (result != Result::OK) { return result; } @@ -276,17 +275,17 @@ Result CreateTotalBumpTransaction(const CWallet* wallet, const uint256& txid, co } -Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors, +Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors, CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx) { // We are going to modify coin control later, copy to re-use CCoinControl new_coin_control(coin_control); - auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); + auto locked_chain = wallet.chain().lock(); + LOCK(wallet.cs_wallet); errors.clear(); - auto it = wallet->mapWallet.find(txid); - if (it == wallet->mapWallet.end()) { + auto it = wallet.mapWallet.find(txid); + if (it == wallet.mapWallet.end()) { errors.push_back("Invalid or non-wallet transaction id"); return Result::INVALID_ADDRESS_OR_KEY; } @@ -300,7 +299,7 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo // Fill in recipients(and preserve a single change key if there is one) std::vector<CRecipient> recipients; for (const auto& output : wtx.tx->vout) { - if (!wallet->IsChange(output)) { + if (!wallet.IsChange(output)) { CRecipient recipient = {output.scriptPubKey, output.nValue, false}; recipients.push_back(recipient); } else { @@ -313,8 +312,8 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo if (coin_control.m_feerate) { // The user provided a feeRate argument. // We calculate this here to avoid compiler warning on the cs_wallet lock - const int64_t maxTxSize = CalculateMaximumSignedTxSize(*wtx.tx, wallet); - Result res = CheckFeeRate(wallet, wtx, *(new_coin_control.m_feerate), maxTxSize, errors); + const int64_t maxTxSize = CalculateMaximumSignedTxSize(*wtx.tx, &wallet); + Result res = CheckFeeRate(wallet, wtx, *new_coin_control.m_feerate, maxTxSize, errors); if (res != Result::OK) { return res; } @@ -342,7 +341,7 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo CAmount fee_ret; int change_pos_in_out = -1; // No requested location for change std::string fail_reason; - if (!wallet->CreateTransaction(*locked_chain, recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) { + if (!wallet.CreateTransaction(*locked_chain, recipients, tx_new, fee_ret, change_pos_in_out, fail_reason, new_coin_control, false)) { errors.push_back("Unable to create transaction: " + fail_reason); return Result::WALLET_ERROR; } @@ -353,7 +352,7 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo // Write back transaction mtx = CMutableTransaction(*tx_new); // Mark new tx not replaceable, if requested. - if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet->m_signal_rbf)) { + if (!coin_control.m_signal_bip125_rbf.get_value_or(wallet.m_signal_rbf)) { for (auto& input : mtx.vin) { if (input.nSequence < 0xfffffffe) input.nSequence = 0xfffffffe; } @@ -362,21 +361,21 @@ Result CreateRateBumpTransaction(CWallet* wallet, const uint256& txid, const CCo return Result::OK; } -bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx) { - auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); - return wallet->SignTransaction(mtx); +bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx) { + auto locked_chain = wallet.chain().lock(); + LOCK(wallet.cs_wallet); + return wallet.SignTransaction(mtx); } -Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid) +Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, uint256& bumped_txid) { - auto locked_chain = wallet->chain().lock(); - LOCK(wallet->cs_wallet); + auto locked_chain = wallet.chain().lock(); + LOCK(wallet.cs_wallet); if (!errors.empty()) { return Result::MISC_ERROR; } - auto it = txid.IsNull() ? wallet->mapWallet.end() : wallet->mapWallet.find(txid); - if (it == wallet->mapWallet.end()) { + auto it = txid.IsNull() ? wallet.mapWallet.end() : wallet.mapWallet.find(txid); + if (it == wallet.mapWallet.end()) { errors.push_back("Invalid or non-wallet transaction id"); return Result::MISC_ERROR; } @@ -393,22 +392,11 @@ Result CommitTransaction(CWallet* wallet, const uint256& txid, CMutableTransacti mapValue_t mapValue = oldWtx.mapValue; mapValue["replaces_txid"] = oldWtx.GetHash().ToString(); - CValidationState state; - if (!wallet->CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm, state)) { - // NOTE: CommitTransaction never returns false, so this should never happen. - errors.push_back(strprintf("The transaction was rejected: %s", FormatStateMessage(state))); - return Result::WALLET_ERROR; - } - - bumped_txid = tx->GetHash(); - if (state.IsInvalid()) { - // This can happen if the mempool rejected the transaction. Report - // what happened in the "errors" response. - errors.push_back(strprintf("Error: The transaction was rejected: %s", FormatStateMessage(state))); - } + wallet.CommitTransaction(tx, std::move(mapValue), oldWtx.vOrderForm); // mark the original tx as bumped - if (!wallet->MarkReplaced(oldWtx.GetHash(), bumped_txid)) { + bumped_txid = tx->GetHash(); + if (!wallet.MarkReplaced(oldWtx.GetHash(), bumped_txid)) { // TODO: see if JSON-RPC has a standard way of returning a response // along with an exception. It would be good to return information about // wtxBumped to the caller even if marking the original transaction diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h index 0c4e1cb7dd..9357397606 100644 --- a/src/wallet/feebumper.h +++ b/src/wallet/feebumper.h @@ -26,7 +26,7 @@ enum class Result }; //! Return whether transaction can be bumped. -bool TransactionCanBeBumped(const CWallet* wallet, const uint256& txid); +bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid); //! Create bumpfee transaction based on total amount. Result CreateTotalBumpTransaction(const CWallet* wallet, @@ -39,7 +39,7 @@ Result CreateTotalBumpTransaction(const CWallet* wallet, CMutableTransaction& mtx); //! Create bumpfee transaction based on feerate estimates. -Result CreateRateBumpTransaction(CWallet* wallet, +Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<std::string>& errors, @@ -50,13 +50,13 @@ Result CreateRateBumpTransaction(CWallet* wallet, //! Sign the new transaction, //! @return false if the tx couldn't be found or if it was //! impossible to create the signature(s) -bool SignTransaction(CWallet* wallet, CMutableTransaction& mtx); +bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx); //! Commit the bumpfee transaction. //! @return success in case of CWallet::CommitTransaction was successful, //! but sets errors if the tx could not be added to the mempool (will try later) //! or if the old transaction could not be marked as replaced. -Result CommitTransaction(CWallet* wallet, +Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransaction&& mtx, std::vector<std::string>& errors, diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp index 2792058f2a..249bc833c6 100644 --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -5,7 +5,6 @@ #include <wallet/fees.h> -#include <util/system.h> #include <wallet/coincontrol.h> #include <wallet/wallet.h> diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 43b6ead028..3657a157b6 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -11,7 +11,6 @@ #include <util/system.h> #include <util/translation.h> #include <wallet/wallet.h> -#include <wallet/walletutil.h> #include <walletinitinterface.h> class WalletInit : public WalletInitInterface { @@ -122,8 +121,6 @@ bool WalletInit::ParameterInteraction() const if (gArgs.GetBoolArg("-sysperms", false)) return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); - if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false)) - return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.").translated); return true; } diff --git a/src/wallet/ismine.cpp b/src/wallet/ismine.cpp index b7ef2d4490..029b922785 100644 --- a/src/wallet/ismine.cpp +++ b/src/wallet/ismine.cpp @@ -7,7 +7,6 @@ #include <key.h> #include <script/script.h> -#include <script/sign.h> #include <script/signingprovider.h> #include <wallet/wallet.h> diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp index b5d3b8c305..071befaebf 100644 --- a/src/wallet/load.cpp +++ b/src/wallet/load.cpp @@ -7,6 +7,7 @@ #include <interfaces/chain.h> #include <scheduler.h> +#include <util/string.h> #include <util/system.h> #include <util/translation.h> #include <wallet/wallet.h> @@ -53,10 +54,10 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal } std::string error_string; - std::string warning_string; - bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warning_string); + std::vector<std::string> warnings; + bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warnings); if (!error_string.empty()) chain.initError(error_string); - if (!warning_string.empty()) chain.initWarning(warning_string); + if (!warnings.empty()) chain.initWarning(Join(warnings, "\n")); if (!verify_success) return false; } @@ -66,8 +67,12 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files) { for (const std::string& walletFile : wallet_files) { - std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile)); + std::string error; + std::vector<std::string> warnings; + std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile), error, warnings); + if (!warnings.empty()) chain.initWarning(Join(warnings, "\n")); if (!pwallet) { + chain.initError(error); return false; } AddWallet(pwallet); diff --git a/src/wallet/psbtwallet.h b/src/wallet/psbtwallet.h index a24a0967d2..a7e52df6d9 100644 --- a/src/wallet/psbtwallet.h +++ b/src/wallet/psbtwallet.h @@ -5,9 +5,7 @@ #ifndef BITCOIN_WALLET_PSBTWALLET_H #define BITCOIN_WALLET_PSBTWALLET_H -#include <node/transaction.h> #include <psbt.h> -#include <primitives/transaction.h> #include <wallet/wallet.h> /** diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index f52e4318c8..1cd4cb93b4 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -7,7 +7,6 @@ #include <interfaces/chain.h> #include <key_io.h> #include <merkleblock.h> -#include <rpc/server.h> #include <rpc/util.h> #include <script/descriptor.h> #include <script/script.h> diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index dc437e5cd8..e571501221 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4,12 +4,10 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <amount.h> -#include <consensus/validation.h> #include <core_io.h> #include <init.h> #include <interfaces/chain.h> #include <key_io.h> -#include <node/transaction.h> #include <outputtype.h> #include <policy/feerate.h> #include <policy/fees.h> @@ -22,6 +20,7 @@ #include <util/bip32.h> #include <util/fees.h> #include <util/moneystr.h> +#include <util/string.h> #include <util/system.h> #include <util/url.h> #include <util/validation.h> @@ -37,7 +36,6 @@ #include <univalue.h> -#include <functional> static const std::string WALLET_ENDPOINT_BASE = "/wallet/"; @@ -342,11 +340,7 @@ static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired)); throw JSONRPCError(RPC_WALLET_ERROR, strError); } - CValidationState state; - if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, state)) { - strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(state)); - throw JSONRPCError(RPC_WALLET_ERROR, strError); - } + pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */); return tx; } @@ -927,12 +921,7 @@ static UniValue sendmany(const JSONRPCRequest& request) bool fCreated = pwallet->CreateTransaction(*locked_chain, vecSend, tx, nFeeRequired, nChangePosRet, strFailReason, coin_control); if (!fCreated) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); - CValidationState state; - if (!pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */, state)) { - strFailReason = strprintf("Transaction commit failed:: %s", FormatStateMessage(state)); - throw JSONRPCError(RPC_WALLET_ERROR, strFailReason); - } - + pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */); return tx->GetHash().GetHex(); } @@ -2583,13 +2572,14 @@ static UniValue loadwallet(const JSONRPCRequest& request) } } - std::string error, warning; + std::string error; + std::vector<std::string> warning; std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_interfaces->chain, location, error, warning); if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error); UniValue obj(UniValue::VOBJ); obj.pushKV("name", wallet->GetName()); - obj.pushKV("warning", warning); + obj.pushKV("warning", Join(warning, "\n")); return obj; } @@ -2695,12 +2685,12 @@ static UniValue createwallet(const JSONRPCRequest& request) } SecureString passphrase; passphrase.reserve(100); - std::string warning; + std::vector<std::string> warnings; if (!request.params[3].isNull()) { passphrase = request.params[3].get_str().c_str(); if (passphrase.empty()) { // Empty string means unencrypted - warning = "Empty string given as passphrase, wallet will not be encrypted."; + warnings.emplace_back("Empty string given as passphrase, wallet will not be encrypted."); } } @@ -2709,9 +2699,8 @@ static UniValue createwallet(const JSONRPCRequest& request) } std::string error; - std::string create_warning; std::shared_ptr<CWallet> wallet; - WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, create_warning, wallet); + WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, warnings, wallet); switch (status) { case WalletCreationStatus::CREATION_FAILED: throw JSONRPCError(RPC_WALLET_ERROR, error); @@ -2722,15 +2711,9 @@ static UniValue createwallet(const JSONRPCRequest& request) // no default case, so the compiler can warn about missing cases } - if (warning.empty()) { - warning = create_warning; - } else if (!warning.empty() && !create_warning.empty()){ - warning += "; " + create_warning; - } - UniValue obj(UniValue::VOBJ); obj.pushKV("name", wallet->GetName()); - obj.pushKV("warning", warning); + obj.pushKV("warning", Join(warnings, "\n")); return obj; } @@ -3417,7 +3400,7 @@ static UniValue bumpfee(const JSONRPCRequest& request) res = feebumper::CreateTotalBumpTransaction(pwallet, hash, coin_control, totalFee, errors, old_fee, new_fee, mtx); } else { // Targeting feerate bump. - res = feebumper::CreateRateBumpTransaction(pwallet, hash, coin_control, errors, old_fee, new_fee, mtx); + res = feebumper::CreateRateBumpTransaction(*pwallet, hash, coin_control, errors, old_fee, new_fee, mtx); } if (res != feebumper::Result::OK) { switch(res) { @@ -3440,12 +3423,12 @@ static UniValue bumpfee(const JSONRPCRequest& request) } // sign bumped transaction - if (!feebumper::SignTransaction(pwallet, mtx)) { + if (!feebumper::SignTransaction(*pwallet, mtx)) { throw JSONRPCError(RPC_WALLET_ERROR, "Can't sign transaction."); } // commit the bumped transaction uint256 txid; - if (feebumper::CommitTransaction(pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) { + if (feebumper::CommitTransaction(*pwallet, hash, std::move(mtx), errors, txid) != feebumper::Result::OK) { throw JSONRPCError(RPC_WALLET_ERROR, errors[0]); } UniValue result(UniValue::VOBJ); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 73523ca36d..a2b2a7b227 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -8,7 +8,6 @@ #include <stdint.h> #include <vector> -#include <consensus/validation.h> #include <interfaces/chain.h> #include <policy/policy.h> #include <rpc/server.h> @@ -451,8 +450,7 @@ public: auto locked_chain = m_chain->lock(); BOOST_CHECK(wallet->CreateTransaction(*locked_chain, {recipient}, tx, fee, changePos, error, dummy)); } - CValidationState state; - BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, state)); + wallet->CommitTransaction(tx, {}, {}); CMutableTransaction blocktx; { LOCK(wallet->cs_wallet); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 09f08220db..159d4f78c6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -27,13 +27,11 @@ #include <util/rbf.h> #include <util/translation.h> #include <util/validation.h> -#include <validation.h> #include <wallet/coincontrol.h> #include <wallet/fees.h> #include <algorithm> #include <assert.h> -#include <future> #include <boost/algorithm/string/replace.hpp> @@ -140,16 +138,16 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet) } } -std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning) +std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings) { - if (!CWallet::Verify(chain, location, false, error, warning)) { + if (!CWallet::Verify(chain, location, false, error, warnings)) { error = "Wallet file verification failed: " + error; return nullptr; } - std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location); + std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings); if (!wallet) { - error = "Wallet loading failed."; + error = "Wallet loading failed: " + error; return nullptr; } AddWallet(wallet); @@ -157,12 +155,12 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocati return wallet; } -std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning) +std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings) { - return LoadWallet(chain, WalletLocation(name), error, warning); + return LoadWallet(chain, WalletLocation(name), error, warnings); } -WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result) +WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result) { // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET); @@ -180,9 +178,8 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& } // Wallet::Verify will check if we're trying to create a wallet with a duplicate name. - std::string wallet_error; - if (!CWallet::Verify(chain, location, false, wallet_error, warning)) { - error = "Wallet file verification failed: " + wallet_error; + if (!CWallet::Verify(chain, location, false, error, warnings)) { + error = "Wallet file verification failed: " + error; return WalletCreationStatus::CREATION_FAILED; } @@ -193,9 +190,9 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& } // Make the wallet - std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, wallet_creation_flags); + std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings, wallet_creation_flags); if (!wallet) { - error = "Wallet creation failed"; + error = "Wallet creation failed: " + error; return WalletCreationStatus::CREATION_FAILED; } @@ -2739,8 +2736,11 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm } std::vector<OutputGroup> groups = GroupOutputs(vCoins, !coin_control.m_avoid_partial_spends); - size_t max_ancestors = (size_t)std::max<int64_t>(1, gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT)); - size_t max_descendants = (size_t)std::max<int64_t>(1, gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)); + unsigned int limit_ancestor_count; + unsigned int limit_descendant_count; + chain().getPackageLimits(limit_ancestor_count, limit_descendant_count); + size_t max_ancestors = (size_t)std::max<int64_t>(1, limit_ancestor_count); + size_t max_descendants = (size_t)std::max<int64_t>(1, limit_descendant_count); bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS); bool res = nTargetValue <= nValueFromPresetInputs || @@ -3284,51 +3284,44 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std return true; } -/** - * Call after CreateTransaction unless you want to abort - */ -bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CValidationState& state) +void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm) { - { - auto locked_chain = chain().lock(); - LOCK(cs_wallet); + auto locked_chain = chain().lock(); + LOCK(cs_wallet); - CWalletTx wtxNew(this, std::move(tx)); - wtxNew.mapValue = std::move(mapValue); - wtxNew.vOrderForm = std::move(orderForm); - wtxNew.fTimeReceivedIsTxTime = true; - wtxNew.fFromMe = true; + CWalletTx wtxNew(this, std::move(tx)); + wtxNew.mapValue = std::move(mapValue); + wtxNew.vOrderForm = std::move(orderForm); + wtxNew.fTimeReceivedIsTxTime = true; + wtxNew.fFromMe = true; - WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */ - { + WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */ - // Add tx to wallet, because if it has change it's also ours, - // otherwise just for transaction history. - AddToWallet(wtxNew); + // Add tx to wallet, because if it has change it's also ours, + // otherwise just for transaction history. + AddToWallet(wtxNew); - // Notify that old coins are spent - for (const CTxIn& txin : wtxNew.tx->vin) - { - CWalletTx &coin = mapWallet.at(txin.prevout.hash); - coin.BindWallet(this); - NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED); - } - } + // Notify that old coins are spent + for (const CTxIn& txin : wtxNew.tx->vin) { + CWalletTx &coin = mapWallet.at(txin.prevout.hash); + coin.BindWallet(this); + NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED); + } - // Get the inserted-CWalletTx from mapWallet so that the - // fInMempool flag is cached properly - CWalletTx& wtx = mapWallet.at(wtxNew.GetHash()); + // Get the inserted-CWalletTx from mapWallet so that the + // fInMempool flag is cached properly + CWalletTx& wtx = mapWallet.at(wtxNew.GetHash()); - if (fBroadcastTransactions) - { - std::string err_string; - if (!wtx.SubmitMemoryPoolAndRelay(err_string, true, *locked_chain)) { - WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string); - // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure. - } - } + if (!fBroadcastTransactions) { + // Don't submit tx to the mempool + return; + } + + std::string err_string; + if (!wtx.SubmitMemoryPoolAndRelay(err_string, true, *locked_chain)) { + WalletLogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", err_string); + // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure. } - return true; } DBErrors CWallet::LoadWallet(bool& fFirstRunRet) @@ -3467,21 +3460,6 @@ bool CWallet::DelAddressBook(const CTxDestination& address) return WalletBatch(*database).EraseName(EncodeDestination(address)); } -const std::string& CWallet::GetLabelName(const CScript& scriptPubKey) const -{ - CTxDestination address; - if (ExtractDestination(scriptPubKey, address) && !scriptPubKey.IsUnspendable()) { - auto mi = mapAddressBook.find(address); - if (mi != mapAddressBook.end()) { - return mi->second.name; - } - } - // A scriptPubKey that doesn't have an entry in the address book is - // associated with the default label (""). - const static std::string DEFAULT_LABEL_NAME; - return DEFAULT_LABEL_NAME; -} - /** * Mark old keypool keys as used, * and generate all new keys @@ -4196,7 +4174,7 @@ void CWallet::MarkPreSplitKeys() } } -bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string) +bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::vector<std::string>& warnings) { // Do some checking on wallet path. It should be either a: // @@ -4250,10 +4228,10 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, b } } - return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string); + return WalletBatch::VerifyDatabaseFile(wallet_path, warnings, error_string); } -std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags) +std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings, uint64_t wallet_creation_flags) { const std::string walletFile = WalletDataFilePath(location.GetPath()).string(); @@ -4266,7 +4244,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(&chain, location, WalletDatabase::Create(location.GetPath())); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DBErrors::LOAD_OK) { - chain.initError(strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile)); + error = strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile); return nullptr; } } @@ -4279,29 +4257,28 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, // should be possible to use std::allocate_shared. std::shared_ptr<CWallet> walletInstance(new CWallet(&chain, location, WalletDatabase::Create(location.GetPath())), ReleaseWallet); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); - if (nLoadWalletRet != DBErrors::LOAD_OK) - { + if (nLoadWalletRet != DBErrors::LOAD_OK) { if (nLoadWalletRet == DBErrors::CORRUPT) { - chain.initError(strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile)); + error = strprintf(_("Error loading %s: Wallet corrupted").translated, walletFile); return nullptr; } else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR) { - chain.initWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" + warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data" " or address book entries might be missing or incorrect.").translated, walletFile)); } else if (nLoadWalletRet == DBErrors::TOO_NEW) { - chain.initError(strprintf(_("Error loading %s: Wallet requires newer version of %s").translated, walletFile, PACKAGE_NAME)); + error = strprintf(_("Error loading %s: Wallet requires newer version of %s").translated, walletFile, PACKAGE_NAME); return nullptr; } else if (nLoadWalletRet == DBErrors::NEED_REWRITE) { - chain.initError(strprintf(_("Wallet needed to be rewritten: restart %s to complete").translated, PACKAGE_NAME)); + error = strprintf(_("Wallet needed to be rewritten: restart %s to complete").translated, PACKAGE_NAME); return nullptr; } else { - chain.initError(strprintf(_("Error loading %s").translated, walletFile)); + error = strprintf(_("Error loading %s").translated, walletFile); return nullptr; } } @@ -4320,7 +4297,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); if (nMaxVersion < walletInstance->GetVersion()) { - chain.initError(_("Cannot downgrade wallet").translated); + error = _("Cannot downgrade wallet").translated; return nullptr; } walletInstance->SetMaxVersion(nMaxVersion); @@ -4333,7 +4310,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT int max_version = walletInstance->GetVersion(); if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) { - chain.initError(_("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.").translated); + error = _("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.").translated; return nullptr; } @@ -4361,7 +4338,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Regenerate the keypool if upgraded to HD if (hd_upgrade) { if (!walletInstance->TopUpKeyPool()) { - chain.initError(_("Unable to generate keys").translated); + error = _("Unable to generate keys").translated; return nullptr; } } @@ -4381,7 +4358,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, // Top up the keypool if (walletInstance->CanGenerateKeys() && !walletInstance->TopUpKeyPool()) { - chain.initError(_("Unable to generate initial keys").translated); + error = _("Unable to generate initial keys").translated; return nullptr; } @@ -4389,33 +4366,33 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, walletInstance->ChainStateFlushed(locked_chain->getTipLocator()); } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) { // Make it impossible to disable private keys after creation - chain.initError(strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, walletFile)); + error = strprintf(_("Error loading %s: Private keys can only be disabled during creation").translated, walletFile); return NULL; } else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { LOCK(walletInstance->cs_KeyStore); if (!walletInstance->mapKeys.empty() || !walletInstance->mapCryptedKeys.empty()) { - chain.initWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys").translated, walletFile)); + warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys").translated, walletFile)); } } if (!gArgs.GetArg("-addresstype", "").empty() && !ParseOutputType(gArgs.GetArg("-addresstype", ""), walletInstance->m_default_address_type)) { - chain.initError(strprintf(_("Unknown address type '%s'").translated, gArgs.GetArg("-addresstype", ""))); + error = strprintf(_("Unknown address type '%s'").translated, gArgs.GetArg("-addresstype", "")); return nullptr; } if (!gArgs.GetArg("-changetype", "").empty() && !ParseOutputType(gArgs.GetArg("-changetype", ""), walletInstance->m_default_change_type)) { - chain.initError(strprintf(_("Unknown change type '%s'").translated, gArgs.GetArg("-changetype", ""))); + error = strprintf(_("Unknown change type '%s'").translated, gArgs.GetArg("-changetype", "")); return nullptr; } if (gArgs.IsArgSet("-mintxfee")) { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) { - chain.initError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")).translated); + error = AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")).translated; return nullptr; } if (n > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-mintxfee").translated + " " + + warnings.push_back(AmountHighWarn("-mintxfee").translated + " " + _("This is the minimum transaction fee you pay on every transaction.").translated); } walletInstance->m_min_fee = CFeeRate(n); @@ -4424,11 +4401,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-fallbackfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) { - chain.initError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'").translated, gArgs.GetArg("-fallbackfee", ""))); + error = strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'").translated, gArgs.GetArg("-fallbackfee", "")); return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-fallbackfee").translated + " " + + warnings.push_back(AmountHighWarn("-fallbackfee").translated + " " + _("This is the transaction fee you may pay when fee estimates are not available.").translated); } walletInstance->m_fallback_fee = CFeeRate(nFeePerK); @@ -4439,11 +4416,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-discardfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) { - chain.initError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'").translated, gArgs.GetArg("-discardfee", ""))); + error = strprintf(_("Invalid amount for -discardfee=<amount>: '%s'").translated, gArgs.GetArg("-discardfee", "")); return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-discardfee").translated + " " + + warnings.push_back(AmountHighWarn("-discardfee").translated + " " + _("This is the transaction fee you may discard if change is smaller than dust at this level").translated); } walletInstance->m_discard_rate = CFeeRate(nFeePerK); @@ -4451,41 +4428,40 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-paytxfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) { - chain.initError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")).translated); + error = AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")).translated; return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-paytxfee").translated + " " + + warnings.push_back(AmountHighWarn("-paytxfee").translated + " " + _("This is the transaction fee you will pay if you send a transaction.").translated); } walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000); if (walletInstance->m_pay_tx_fee < chain.relayMinFee()) { - chain.initError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)").translated, - gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString())); + error = strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)").translated, + gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString()); return nullptr; } } - if (gArgs.IsArgSet("-maxtxfee")) - { + if (gArgs.IsArgSet("-maxtxfee")) { CAmount nMaxFee = 0; if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) { - chain.initError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")).translated); + error = AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")).translated; return nullptr; } if (nMaxFee > HIGH_MAX_TX_FEE) { - chain.initWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.").translated); + warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.").translated); } if (CFeeRate(nMaxFee, 1000) < chain.relayMinFee()) { - chain.initError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)").translated, - gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString())); + error = strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)").translated, + gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString()); return nullptr; } walletInstance->m_default_max_tx_fee = nMaxFee; } if (chain.relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) { - chain.initWarning(AmountHighWarn("-minrelaytxfee").translated + " " + + warnings.push_back(AmountHighWarn("-minrelaytxfee").translated + " " + _("The wallet will avoid paying less than the minimum relay fee.").translated); } @@ -4535,7 +4511,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, } if (rescan_height != block_height) { - chain.initError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)").translated); + error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)").translated; return nullptr; } } @@ -4554,7 +4530,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, { WalletRescanReserver reserver(walletInstance.get()); if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) { - chain.initError(_("Failed to rescan the wallet during initialization").translated); + error = _("Failed to rescan the wallet during initialization").translated; return nullptr; } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 006775e83b..85c277ff50 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -11,7 +11,6 @@ #include <interfaces/handler.h> #include <outputtype.h> #include <policy/feerate.h> -#include <script/sign.h> #include <tinyformat.h> #include <ui_interface.h> #include <util/strencodings.h> @@ -48,7 +47,7 @@ bool RemoveWallet(const std::shared_ptr<CWallet>& wallet); bool HasWallets(); std::vector<std::shared_ptr<CWallet>> GetWallets(); std::shared_ptr<CWallet> GetWallet(const std::string& name); -std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning); +std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings); enum class WalletCreationStatus { SUCCESS, @@ -56,7 +55,7 @@ enum class WalletCreationStatus { ENCRYPTION_FAILED }; -WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::string& warning, std::shared_ptr<CWallet>& result); +WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result); //! Default for -keypool static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000; @@ -1147,7 +1146,16 @@ public: */ bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign = true); - bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm, CValidationState& state); + /** + * Submit the transaction to the node's mempool and then relay to peers. + * Should be called after CreateTransaction unless you want to abort + * broadcasting the transaction. + * + * @param tx[in] The transaction to be broadcast. + * @param mapValue[in] key-values to be set on the transaction. + * @param orderForm[in] BIP 70 / BIP 21 order form details to be set on the transaction. + */ + void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm); bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, bool use_max_sig = false) const { @@ -1246,8 +1254,6 @@ public: bool DelAddressBook(const CTxDestination& address); - const std::string& GetLabelName(const CScript& scriptPubKey) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); @@ -1321,10 +1327,10 @@ public: bool MarkReplaced(const uint256& originalHash, const uint256& newHash); //! Verify wallet naming and perform salvage on the wallet if required - static bool Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::string& warning_string); + static bool Verify(interfaces::Chain& chain, const WalletLocation& location, bool salvage_wallet, std::string& error_string, std::vector<std::string>& warnings); /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ - static std::shared_ptr<CWallet> CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags = 0); + static std::shared_ptr<CWallet> CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings, uint64_t wallet_creation_flags = 0); /** * Wallet post-init setup diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 635997afc9..a9e6763c6d 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -5,8 +5,6 @@ #include <wallet/walletdb.h> -#include <consensus/tx_check.h> -#include <consensus/validation.h> #include <fs.h> #include <key_io.h> #include <protocol.h> @@ -218,8 +216,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssKey >> hash; CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef()); ssValue >> wtx; - CValidationState state; - if (!(CheckTransaction(*wtx.tx, state) && (wtx.GetHash() == hash) && state.IsValid())) + if (wtx.GetHash() != hash) return false; // Undo serialize changes in 31600 @@ -729,9 +726,9 @@ bool WalletBatch::VerifyEnvironment(const fs::path& wallet_path, std::string& er return BerkeleyBatch::VerifyEnvironment(wallet_path, errorStr); } -bool WalletBatch::VerifyDatabaseFile(const fs::path& wallet_path, std::string& warningStr, std::string& errorStr) +bool WalletBatch::VerifyDatabaseFile(const fs::path& wallet_path, std::vector<std::string>& warnings, std::string& errorStr) { - return BerkeleyBatch::VerifyDatabaseFile(wallet_path, warningStr, errorStr, WalletBatch::Recover); + return BerkeleyBatch::VerifyDatabaseFile(wallet_path, warnings, errorStr, WalletBatch::Recover); } bool WalletBatch::WriteDestData(const std::string &address, const std::string &key, const std::string &value) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 0fee35934d..b1781d5ccf 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -7,15 +7,12 @@ #define BITCOIN_WALLET_WALLETDB_H #include <amount.h> -#include <primitives/transaction.h> #include <script/sign.h> #include <wallet/db.h> #include <key.h> -#include <list> #include <stdint.h> #include <string> -#include <utility> #include <vector> /** @@ -263,7 +260,7 @@ public: /* verifies the database environment */ static bool VerifyEnvironment(const fs::path& wallet_path, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const fs::path& wallet_path, std::string& warningStr, std::string& errorStr); + static bool VerifyDatabaseFile(const fs::path& wallet_path, std::vector<std::string>& warnings, std::string& errorStr); //! write the hdchain model (external chain child index counter) bool WriteHDChain(const CHDChain& chain); diff --git a/src/wallet/wallettool.h b/src/wallet/wallettool.h index 7ee2505631..bd08da42d6 100644 --- a/src/wallet/wallettool.h +++ b/src/wallet/wallettool.h @@ -5,7 +5,6 @@ #ifndef BITCOIN_WALLET_WALLETTOOL_H #define BITCOIN_WALLET_WALLETTOOL_H -#include <wallet/ismine.h> #include <wallet/wallet.h> namespace WalletTool { |