diff --git a/README.md b/README.md index 8768184f395b..6975c69a107f 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ source software which enables the use of this currency. Pre-Built Binary ---------------- -For more information, as well as an immediately useable, binary version of +For more information, as well as an immediately usable, binary version of the Dash Core software, see https://www.dash.org/downloads/. License diff --git a/contrib/init/dashd.conf b/contrib/init/dashd.conf index 93f7cc12065a..096bcc4adc9f 100644 --- a/contrib/init/dashd.conf +++ b/contrib/init/dashd.conf @@ -16,7 +16,7 @@ expect fork respawn respawn limit 5 120 -kill timeout 60 +kill timeout 600 pre-start script # this will catch non-existent config files diff --git a/contrib/init/dashd.init b/contrib/init/dashd.init index 0013ccfd10d6..7a341702efc3 100644 --- a/contrib/init/dashd.init +++ b/contrib/init/dashd.init @@ -39,7 +39,7 @@ start() { stop() { echo -n $"Stopping $prog: " - killproc $prog + killproc $prog -t600 RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f $lockfile diff --git a/contrib/init/dashd.service b/contrib/init/dashd.service index ed384937b9c3..8bdb2ae207b6 100644 --- a/contrib/init/dashd.service +++ b/contrib/init/dashd.service @@ -24,6 +24,7 @@ ExecStart=/usr/bin/dashd -daemon \ Type=forking PIDFile=/run/dashd/dashd.pid Restart=on-failure +TimeoutStopSec=600 # Directory creation and permissions #################################### diff --git a/doc/reduce-memory.md b/doc/reduce-memory.md index fd99cbca09a5..18988c1d8db1 100644 --- a/doc/reduce-memory.md +++ b/doc/reduce-memory.md @@ -24,8 +24,7 @@ The size of some in-memory caches can be reduced. As caches trade off memory usa ## Number of peers -- `-maxconnections=` - the maximum number of connections, this defaults to `125`. Each active connection takes up some memory. Only significant if incoming - connections are enabled, otherwise the number of connections will never be more than `8`. +- `-maxconnections=` - the maximum number of connections, this defaults to `125`. Each active connection takes up some memory. Only significant if incoming connections are enabled, otherwise the number of connections will never be more than `10`. Of the 10 outbound peers, there can be 8 full outgoing connections and 2 -blocksonly peers, in which case they are block/addr peers, but not tx peers. ## Thread configuration diff --git a/doc/reduce-traffic.md b/doc/reduce-traffic.md index a9d55d291610..fd0f44358a58 100644 --- a/doc/reduce-traffic.md +++ b/doc/reduce-traffic.md @@ -3,8 +3,10 @@ Reduce Traffic Some node operators need to deal with bandwidth caps imposed by their ISPs. -By default, Dash Core allows up to 125 connections to different peers, 8 of -which are outbound. You can therefore, have at most 117 inbound connections. +By default, Dash Core allows up to 125 connections to different peers, 10 of +which are outbound. You can therefore, have at most 115 inbound connections. +Of the 10 outbound peers, there can be 8 full outgoing connections and 2 with +the -blocksonly mode turned on. You can therefore, have at most 115 inbound connections. The default settings can result in relatively significant traffic consumption. @@ -26,7 +28,7 @@ calculating the target. ## 2. Disable "listening" (`-listen=0`) -Disabling listening will result in fewer nodes connected (remember the maximum of 8 +Disabling listening will result in fewer nodes connected (remember the maximum of 10 outbound peers). Fewer nodes will result in less traffic usage as you are relaying blocks and transactions to fewer nodes. @@ -44,7 +46,11 @@ with other peers, you can disable transaction relay. Be reminded of the effects of this setting. - Fee estimation will no longer work. -- Not relaying other's transactions could hurt your privacy if used while a - wallet is loaded or if you use the node to broadcast transactions. +- It sets the flag "-walletbroadcast" to be "0", only if it is currently unset. + Doing so disables the automatic broadcasting of transactions from wallet. Not + relaying other's transactions could hurt your privacy if used while a wallet + is loaded or if you use the node to broadcast transactions. +- If a peer is whitelisted and "-whitelistforcerelay" is set to "1" (which will + also set "whitelistrelay" to "1"), we will still receive and relay their transactions. - It makes block propagation slower because compact block relay can only be used when transaction relay is enabled. diff --git a/src/Makefile.am b/src/Makefile.am index 0bc9600e51de..d2030cbb29ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -724,6 +724,8 @@ endif libdash_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libdash_cli_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libdash_cli_a_SOURCES = \ + compat/stdin.h \ + compat/stdin.cpp \ rpc/client.cpp \ $(BITCOIN_CORE_H) diff --git a/src/coinjoin/util.cpp b/src/coinjoin/util.cpp index 974b8fd4579d..b9bde738b708 100644 --- a/src/coinjoin/util.cpp +++ b/src/coinjoin/util.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include -#include #include #include #include @@ -306,11 +305,7 @@ bool CTransactionBuilder::Commit(std::string& strResult) return false; } - CValidationState state; - if (!pwallet->CommitTransaction(tx, {}, {}, state)) { - strResult = state.GetRejectReason(); - return false; - } + pwallet->CommitTransaction(tx, {}, {}); fKeepKeys = true; diff --git a/src/compat/stdin.cpp b/src/compat/stdin.cpp new file mode 100644 index 000000000000..a818d2242de7 --- /dev/null +++ b/src/compat/stdin.cpp @@ -0,0 +1,72 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include // for fileno(), stdin + +#ifdef WIN32 +#include // for SetStdinEcho() +#include // for isatty() +#else +#include // for SetStdinEcho() +#include // for SetStdinEcho(), isatty() +#include // for StdinReady() +#endif + +#include + +// https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin +void SetStdinEcho(bool enable) +{ +#ifdef WIN32 + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + DWORD mode; + GetConsoleMode(hStdin, &mode); + if (!enable) { + mode &= ~ENABLE_ECHO_INPUT; + } else { + mode |= ENABLE_ECHO_INPUT; + } + SetConsoleMode(hStdin, mode); +#else + struct termios tty; + tcgetattr(STDIN_FILENO, &tty); + if (!enable) { + tty.c_lflag &= ~ECHO; + } else { + tty.c_lflag |= ECHO; + } + (void)tcsetattr(STDIN_FILENO, TCSANOW, &tty); +#endif +} + +bool StdinTerminal() +{ +#ifdef WIN32 + return _isatty(_fileno(stdin)); +#else + return isatty(fileno(stdin)); +#endif +} + +bool StdinReady() +{ + if (!StdinTerminal()) { + return true; + } +#ifdef WIN32 + return false; +#else + struct pollfd fds; + fds.fd = 0; /* this is STDIN */ + fds.events = POLLIN; + return poll(&fds, 1, 0) == 1; +#endif +} + +NoechoInst::NoechoInst() { SetStdinEcho(false); } +NoechoInst::~NoechoInst() { SetStdinEcho(true); } diff --git a/src/compat/stdin.h b/src/compat/stdin.h new file mode 100644 index 000000000000..468fe4d6a6e0 --- /dev/null +++ b/src/compat/stdin.h @@ -0,0 +1,18 @@ +// Copyright (c) 2018 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_COMPAT_STDIN_H +#define BITCOIN_COMPAT_STDIN_H + +struct NoechoInst { + NoechoInst(); + ~NoechoInst(); +}; + +#define NO_STDIN_ECHO() NoechoInst _no_echo + +bool StdinTerminal(); +bool StdinReady(); + +#endif // BITCOIN_COMPAT_STDIN_H diff --git a/src/dash-cli.cpp b/src/dash-cli.cpp index ac4a781e4f89..cddc1eca49da 100644 --- a/src/dash-cli.cpp +++ b/src/dash-cli.cpp @@ -26,6 +26,7 @@ #include #include +#include const std::function G_TRANSLATION_FUN = nullptr; @@ -55,7 +56,8 @@ static void SetupCliArgs() gArgs.AddArg("-rpcwait", "Wait for RPC server to start", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-rpcwallet=", "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to dashd). This changes the RPC endpoint used, e.g. http://127.0.0.1:9998/wallet/", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-stdin", "Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - gArgs.AddArg("-stdinrpcpass", "Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + gArgs.AddArg("-stdinrpcpass", "Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password. When combined with -stdinwalletpassphrase, -stdinrpcpass consumes the first line, and -stdinwalletpassphrase consumes the second.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + gArgs.AddArg("-stdinwalletpassphrase", "Read wallet passphrase from standard input as a single line. When combined with -stdin, the first line from standard input is used for the wallet passphrase.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); SetupChainParamsBaseOptions(); @@ -441,18 +443,47 @@ static int CommandLineRPC(int argc, char *argv[]) } std::string rpcPass; if (gArgs.GetBoolArg("-stdinrpcpass", false)) { + NO_STDIN_ECHO(); + if (!StdinReady()) { + fputs("RPC password> ", stderr); + fflush(stderr); + } if (!std::getline(std::cin, rpcPass)) { throw std::runtime_error("-stdinrpcpass specified but failed to read from standard input"); } + if (StdinTerminal()) { + fputc('\n', stdout); + } gArgs.ForceSetArg("-rpcpassword", rpcPass); } std::vector args = std::vector(&argv[1], &argv[argc]); + if (gArgs.GetBoolArg("-stdinwalletpassphrase", false)) { + NO_STDIN_ECHO(); + std::string walletPass; + if (args.size() < 1 || args[0].substr(0, 16) != "walletpassphrase") { + throw std::runtime_error("-stdinwalletpassphrase is only applicable for walletpassphrase(change)"); + } + if (!StdinReady()) { + fputs("Wallet passphrase> ", stderr); + fflush(stderr); + } + if (!std::getline(std::cin, walletPass)) { + throw std::runtime_error("-stdinwalletpassphrase specified but failed to read from standard input"); + } + if (StdinTerminal()) { + fputc('\n', stdout); + } + args.insert(args.begin() + 1, walletPass); + } if (gArgs.GetBoolArg("-stdin", false)) { // Read one arg per line from stdin and append std::string line; while (std::getline(std::cin, line)) { args.push_back(line); } + if (StdinTerminal()) { + fputc('\n', stdout); + } } std::unique_ptr rh; std::string method; diff --git a/src/init.cpp b/src/init.cpp index e096a3c97d19..fc96dceea19f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -474,7 +474,7 @@ void SetupServerArgs() gArgs.AddArg("-blocksdir=", "Specify directory to hold blocks subdirectory for *.dat files (default: )", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-blocknotify=", "Execute command when the best block changes (%s in cmd is replaced by block hash)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-blockreconstructionextratxn=", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - gArgs.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Transactions from the wallet or RPC are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + gArgs.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Automatic broadcast and rebroadcast of any transactions from inbound peers is disabled, unless '-whitelistforcerelay' is '1', in which case whitelisted peers' transactions will be relayed. RPC transactions are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-conf=", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-datadir=", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS); diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index bd768d8a5a29..8d79b52d1979 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -289,20 +288,14 @@ class WalletImpl : public Wallet } return tx; } - bool commitTransaction(CTransactionRef tx, + void commitTransaction(CTransactionRef tx, WalletValueMap value_map, - WalletOrderForm order_form, - std::string& reject_reason) override + WalletOrderForm order_form) override { auto locked_chain = m_wallet->chain().lock(); LOCK(m_wallet->cs_wallet); CReserveKey m_key(m_wallet.get()); - CValidationState state; - if (!m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form), state)) { - reject_reason = state.GetRejectReason(); - return false; - } - return true; + m_wallet->CommitTransaction(std::move(tx), std::move(value_map), std::move(order_form)); } bool transactionCanBeAbandoned(const uint256& txid) override { return m_wallet->TransactionCanBeAbandoned(txid); } bool abandonTransaction(const uint256& txid) override diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index 1243c6f0be33..d8eed393c8e8 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -166,10 +166,9 @@ class Wallet std::string& fail_reason) = 0; //! Commit transaction. - virtual bool commitTransaction(CTransactionRef tx, + virtual void commitTransaction(CTransactionRef tx, WalletValueMap value_map, - WalletOrderForm order_form, - std::string& reject_reason) = 0; + WalletOrderForm order_form) = 0; //! Return whether transaction can be abandoned. virtual bool transactionCanBeAbandoned(const uint256& txid) = 0; diff --git a/src/psbt.h b/src/psbt.h index 5ec806d14ee3..c288ec1a8682 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -101,6 +101,9 @@ struct PSBTInput template inline void Unserialize(Stream& s) { + // Used for duplicate key detection + std::set> key_lookup; + // Read loop bool found_sep = false; while(!s.empty()) { @@ -121,7 +124,7 @@ struct PSBTInput // Do stuff based on type switch(type) { case PSBT_IN_NON_WITNESS_UTXO: - if (non_witness_utxo) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input non-witness utxo already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Non-witness utxo key is more than one byte type"); @@ -152,7 +155,7 @@ struct PSBTInput break; } case PSBT_IN_SIGHASH: - if (sighash_type > 0) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input sighash type already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Sighash type key is more than one byte type"); @@ -161,7 +164,7 @@ struct PSBTInput break; case PSBT_IN_REDEEMSCRIPT: { - if (!redeem_script.empty()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input redeemScript already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Input redeemScript key is more than one byte type"); @@ -176,7 +179,7 @@ struct PSBTInput } case PSBT_IN_SCRIPTSIG: { - if (!final_script_sig.empty()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input final scriptSig already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Final scriptSig key is more than one byte type"); @@ -245,6 +248,9 @@ struct PSBTOutput template inline void Unserialize(Stream& s) { + // Used for duplicate key detection + std::set> key_lookup; + // Read loop bool found_sep = false; while(!s.empty()) { @@ -266,7 +272,7 @@ struct PSBTOutput switch(type) { case PSBT_OUT_REDEEMSCRIPT: { - if (!redeem_script.empty()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, output redeemScript already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Output redeemScript key is more than one byte type"); @@ -373,6 +379,9 @@ struct PartiallySignedTransaction throw std::ios_base::failure("Invalid PSBT magic bytes"); } + // Used for duplicate key detection + std::set> key_lookup; + // Read global data bool found_sep = false; while(!s.empty()) { @@ -394,7 +403,7 @@ struct PartiallySignedTransaction switch(type) { case PSBT_GLOBAL_UNSIGNED_TX: { - if (tx) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, unsigned tx already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Global unsigned tx key is more than one byte type"); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index cca328eaadc1..57e31116b45e 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -638,8 +638,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn msgParams.second = CClientUIInterface::MSG_WARNING; // This comment is specific to SendCoinsDialog usage of WalletModel::SendCoinsReturn. - // WalletModel::TransactionCommitFailed is used only in WalletModel::sendCoins() - // all others are used only in WalletModel::prepareTransaction() + // All status values are used only in WalletModel::prepareTransaction() switch(sendCoinsReturn.status) { case WalletModel::InvalidAddress: @@ -661,10 +660,6 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn msgParams.first = tr("Transaction creation failed!"); msgParams.second = CClientUIInterface::MSG_ERROR; break; - case WalletModel::TransactionCommitFailed: - msgParams.first = tr("The transaction was rejected with the following reason: %1").arg(sendCoinsReturn.reasonCommitFailed); - msgParams.second = CClientUIInterface::MSG_ERROR; - break; case WalletModel::AbsurdFee: msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->wallet().getDefaultMaxTxFee())); break; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 4e6ba17602d1..7139733821a3 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -312,9 +312,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran } auto& newTx = transaction.getWtx(); - std::string rejectReason; - if (!wallet().commitTransaction(newTx, std::move(mapValue), std::move(vOrderForm), rejectReason)) - return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(rejectReason)); + wallet().commitTransaction(newTx, std::move(mapValue), std::move(vOrderForm)); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << *newTx; diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index df08e6979aaa..2db8d1018036 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -131,7 +131,6 @@ class WalletModel : public QObject AmountWithFeeExceedsBalance, DuplicateAddress, TransactionCreationFailed, // Error returned when wallet is still locked - TransactionCommitFailed, AbsurdFee, PaymentRequestExpired }; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 5d05d1bf7ea0..2fafef54ea18 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -403,7 +403,7 @@ static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) RPCHelpMan{"syncwithvalidationinterfacequeue", "\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n", {}, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("syncwithvalidationinterfacequeue","") + HelpExampleRpc("syncwithvalidationinterfacequeue","") @@ -1773,7 +1773,7 @@ static UniValue preciousblock(const JSONRPCRequest& request) { {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as precious"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("preciousblock", "\"blockhash\"") + HelpExampleRpc("preciousblock", "\"blockhash\"") @@ -1811,7 +1811,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request) { {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as invalid"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("invalidateblock", "\"blockhash\"") + HelpExampleRpc("invalidateblock", "\"blockhash\"") @@ -1853,7 +1853,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request) { {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to reconsider"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("reconsiderblock", "\"blockhash\"") + HelpExampleRpc("reconsiderblock", "\"blockhash\"") @@ -2379,7 +2379,7 @@ static UniValue savemempool(const JSONRPCRequest& request) RPCHelpMan{"savemempool", "\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n", {}, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("savemempool", "") + HelpExampleRpc("savemempool", "") diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index 295d24f910ea..d770c93360db 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include -#include #include #include #include @@ -244,10 +243,7 @@ static UniValue gobject_prepare(const JSONRPCRequest& request) } // -- send the tx to the network - CValidationState state; - if (!pwallet->CommitTransaction(tx, {}, {}, state)) { - throw JSONRPCError(RPC_INTERNAL_ERROR, "CommitTransaction failed! Reason given: " + state.GetRejectReason()); - } + pwallet->CommitTransaction(tx, {}, {}); LogPrint(BCLog::GOBJECT, "gobject_prepare -- GetDataAsPlainString = %s, hash = %s, txid = %s\n", govobj.GetDataAsPlainString(), govobj.GetHash().ToString(), tx->GetHash().ToString()); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 378b4afa7fe8..bcd13f9244fd 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -741,7 +741,7 @@ static UniValue submitblock(const JSONRPCRequest& request) {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block data to submit"}, {"dummy", RPCArg::Type::STR, /* default */ "ignored", "dummy value, for compatibility with BIP22. This value is ignored."}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", "Returns JSON Null when valid, a string according to BIP22 otherwise"}, RPCExamples{ HelpExampleCli("submitblock", "\"mydata\"") + HelpExampleRpc("submitblock", "\"mydata\"") diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 8db23379dafc..7f6c109c626c 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -530,7 +530,7 @@ static UniValue setmocktime(const JSONRPCRequest& request) {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Unix seconds-since-epoch timestamp\n" " Pass 0 to go back to using the system time."}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{""}, }.ToString() ); @@ -1278,7 +1278,7 @@ static UniValue echo(const JSONRPCRequest& request) "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in " "dash-cli and the GUI. There is no server-side difference.", {}, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", "Returns whatever was passed in"}, RPCExamples{""}, }.ToString() ); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 96c1c51e9351..7c7183b1a2f2 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -57,7 +57,7 @@ static UniValue ping(const JSONRPCRequest& request) "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n", {}, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("ping", "") + HelpExampleRpc("ping", "") @@ -254,7 +254,7 @@ static UniValue addnode(const JSONRPCRequest& request) {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"}, {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("addnode", "\"192.168.0.6:9999\" \"onetry\"") + HelpExampleRpc("addnode", "\"192.168.0.6:9999\", \"onetry\"") @@ -299,7 +299,7 @@ static UniValue disconnectnode(const JSONRPCRequest& request) {"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"}, {"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("disconnectnode", "\"192.168.0.6:9999\"") + HelpExampleCli("disconnectnode", "\"\" 1") @@ -591,7 +591,7 @@ static UniValue setban(const JSONRPCRequest& request) {"bantime", RPCArg::Type::NUM, /* default */ "0", "time in seconds how long (or until when if [absolute] is set) the IP is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)"}, {"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp in seconds since epoch (Jan 1 1970 GMT)"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") @@ -668,7 +668,16 @@ static UniValue listbanned(const JSONRPCRequest& request) RPCHelpMan{"listbanned", "\nList all banned IPs/Subnets.\n", {}, - RPCResults{}, + RPCResult{RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", ""}, + {RPCResult::Type::NUM_TIME, "banned_until", ""}, + {RPCResult::Type::NUM_TIME, "ban_created", ""}, + {RPCResult::Type::STR, "ban_reason", ""}, + }}, + }}, RPCExamples{ HelpExampleCli("listbanned", "") + HelpExampleRpc("listbanned", "") @@ -705,7 +714,7 @@ static UniValue clearbanned(const JSONRPCRequest& request) RPCHelpMan{"clearbanned", "\nClear all banned IPs.\n", {}, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("clearbanned", "") + HelpExampleRpc("clearbanned", "") @@ -729,7 +738,7 @@ static UniValue setnetworkactive(const JSONRPCRequest& request) { {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"}, RPCExamples{""}, }.ToString() ); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index fb8c65be0c3e..16349d578c27 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -179,6 +179,7 @@ UniValue help(const JSONRPCRequest& jsonRequest) UniValue stop(const JSONRPCRequest& jsonRequest) { + static const std::string RESULT{PACKAGE_NAME " stopping"}; // Accept the deprecated and ignored 'detach' boolean argument // Also accept the hidden 'wait' integer argument (milliseconds) // For instance, 'stop 1000' makes the call wait 1 second before returning @@ -188,7 +189,7 @@ UniValue stop(const JSONRPCRequest& jsonRequest) RPCHelpMan{"stop", "\nStop Dash Core server.", {}, - RPCResults{}, + RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"}, RPCExamples{""}, }.ToString()); // Event loop will exit after current HTTP requests have been handled, so @@ -197,7 +198,7 @@ UniValue stop(const JSONRPCRequest& jsonRequest) if (jsonRequest.params[0].isNum()) { UninterruptibleSleep(std::chrono::milliseconds{jsonRequest.params[0].get_int()}); } - return "Dash Core server stopping"; + return RESULT; } static UniValue uptime(const JSONRPCRequest& jsonRequest) diff --git a/src/rpc/util.h b/src/rpc/util.h index 94dd708f38c6..cf469afe9a84 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -326,11 +326,6 @@ struct RPCResult { struct RPCResults { const std::vector m_results; - RPCResults() - : m_results{} - { - } - RPCResults(RPCResult result) : m_results{{result}} { diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 61449a885364..463b1c0b7c72 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -36,7 +36,7 @@ namespace { // xpubs use other characters too, but already have their own checksum // mechanism. // * Function names like "multi()" use other characters, but mistakes in -// these would generally result in an unparseable descriptor. +// these would generally result in an unparsable descriptor. // * A case error always counts as 1 symbol error. // * Any other 1 character substitution error counts as 1 or 2 symbol errors. // * Any 1 symbol error is always detected. diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index e93ebad60d49..7a3c96b2bd40 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -151,17 +151,23 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) LOCK(cs_main); tip = ::ChainActive().Tip(); } - CScript coinbase_script_pub_key = GetScriptForDestination(coinbaseKey.GetPubKey().GetID()); + CKey coinbase_key_A, coinbase_key_B; + coinbase_key_A.MakeNewKey(true); + coinbase_key_B.MakeNewKey(true); + CScript coinbase_script_pub_key_A = GetScriptForDestination(coinbase_key_A.GetPubKey().GetID()); + CScript coinbase_script_pub_key_B = GetScriptForDestination(coinbase_key_B.GetPubKey().GetID()); std::vector> chainA, chainB; - BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainA)); - BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key, 10, chainB)); + BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key_A, 10, chainA)); + BOOST_REQUIRE(BuildChain(tip, coinbase_script_pub_key_B, 10, chainB)); // Check that new blocks on chain A get indexed. uint256 chainA_last_header = last_header; for (size_t i = 0; i < 2; i++) { const auto& block = chainA[i]; BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); - + } + for (size_t i = 0; i < 2; i++) { + const auto& block = chainA[i]; const CBlockIndex* block_index; { LOCK(cs_main); @@ -177,7 +183,9 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) for (size_t i = 0; i < 3; i++) { const auto& block = chainB[i]; BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); - + } + for (size_t i = 0; i < 3; i++) { + const auto& block = chainB[i]; const CBlockIndex* block_index; { LOCK(cs_main); @@ -205,7 +213,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) // Reorg back to chain A. for (size_t i = 2; i < 4; i++) { const auto& block = chainA[i]; - BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); } // Check that chain A and B blocks can be retrieved. diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index a588d9f3edc1..8728dc8ceef4 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -81,7 +81,7 @@ UniValue importprivkey(const JSONRPCRequest& request) {"label", RPCArg::Type::STR, /* default */ "current label if address exists, otherwise \"\"", "An optional label"}, {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ "\nDump a private key\n" + HelpExampleCli("dumpprivkey", "\"myaddress\"") + @@ -173,7 +173,7 @@ UniValue abortrescan(const JSONRPCRequest& request) RPCHelpMan{"abortrescan", "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n", {}, - RPCResults{}, + RPCResult{RPCResult::Type::BOOL, "", "Whether the abort was successful"}, RPCExamples{ "\nImport a private key\n" + HelpExampleCli("importprivkey", "\"mykey\"") + @@ -249,7 +249,7 @@ UniValue importaddress(const JSONRPCRequest& request) {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"}, {"p2sh", RPCArg::Type::BOOL, /* default */ "false", "Add the P2SH version of the script as well"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ "\nImport an address with rescan\n" + HelpExampleCli("importaddress", "\"myaddress\"") + @@ -330,7 +330,7 @@ UniValue importprunedfunds(const JSONRPCRequest& request) {"rawtransaction", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A raw transaction in hex funding an already-existing address in wallet"}, {"txoutproof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex output from gettxoutproof that contains the transaction"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{""}, }.ToString() ); @@ -396,7 +396,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request) { {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded id of the transaction you are deleting"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") + "\nAs a JSON-RPC call\n" @@ -442,7 +442,7 @@ UniValue importpubkey(const JSONRPCRequest& request) {"label", RPCArg::Type::STR, /* default */ "\"\"", "An optional label"}, {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ "\nImport a public key with rescan\n" + HelpExampleCli("importpubkey", "\"mypubkey\"") + @@ -516,7 +516,7 @@ UniValue importwallet(const JSONRPCRequest& request) { {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet file"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ "\nDump the wallet\n" + HelpExampleCli("dumpwallet", "\"test\"") + diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 862e8a812072..cd78d46c4068 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -244,7 +243,7 @@ static UniValue setlabel(const JSONRPCRequest& request) {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The dash address to be associated with a label."}, {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label to assign to the address."}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("setlabel", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"tabby\"") + HelpExampleRpc("setlabel", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", \"tabby\"") @@ -309,11 +308,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; } @@ -798,7 +793,7 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request) RPCHelpMan{"getunconfirmedbalance", "Returns the server's total unconfirmed balance\n", {}, - RPCResults{}, + RPCResult{RPCResult::Type::NUM, "", "The balance"}, RPCExamples{""}, }.ToString()); @@ -956,12 +951,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(); } @@ -1765,7 +1755,7 @@ static UniValue abandontransaction(const JSONRPCRequest& request) { {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") @@ -1807,7 +1797,7 @@ static UniValue backupwallet(const JSONRPCRequest& request) { {"destination", RPCArg::Type::STR, RPCArg::Optional::NO, "The destination directory or file"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("backupwallet", "\"backup.dat\"") + HelpExampleRpc("backupwallet", "\"backup.dat\"") @@ -1844,7 +1834,7 @@ static UniValue keypoolrefill(const JSONRPCRequest& request) { {"newsize", RPCArg::Type::NUM, /* default */ itostr(DEFAULT_KEYPOOL_SIZE), "The new keypool size"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("keypoolrefill", "") + HelpExampleRpc("keypoolrefill", "") @@ -1896,7 +1886,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request) {"timeout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The time to keep the decryption key in seconds; capped at 100000000 (~3 years)."}, {"mixingonly", RPCArg::Type::BOOL, /* default */ "false", "If is true sending functions are disabled."}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ "\nUnlock the wallet for 60 seconds\n" + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") + @@ -1989,7 +1979,7 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request) {"oldpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The current passphrase"}, {"newpassphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The new passphrase"}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"") + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"") @@ -2039,7 +2029,7 @@ static UniValue walletlock(const JSONRPCRequest& request) "After calling this method, you will need to call walletpassphrase again\n" "before being able to call any methods which require the wallet to be unlocked.\n", {}, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ "\nSet the passphrase for 2 minutes to perform a transaction\n" + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") + @@ -2084,7 +2074,7 @@ static UniValue encryptwallet(const JSONRPCRequest& request) { {"passphrase", RPCArg::Type::STR, RPCArg::Optional::NO, "The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long."}, }, - RPCResults{}, + RPCResult{RPCResult::Type::STR, "", "A string with further instructions"}, RPCExamples{ "\nEncrypt your wallet\n" + HelpExampleCli("encryptwallet", "\"my pass phrase\"") + @@ -2861,7 +2851,7 @@ static UniValue unloadwallet(const JSONRPCRequest& request) { {"wallet_name", RPCArg::Type::STR, /* default */ "the wallet name from the RPC request", "The name of the wallet to unload."}, }, - RPCResults{}, + RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ HelpExampleCli("unloadwallet", "wallet_name") + HelpExampleRpc("unloadwallet", "wallet_name") diff --git a/src/wallet/test/coinjoin_tests.cpp b/src/wallet/test/coinjoin_tests.cpp index db4bcdebeeaa..fe2a7af05909 100644 --- a/src/wallet/test/coinjoin_tests.cpp +++ b/src/wallet/test/coinjoin_tests.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -122,8 +121,7 @@ class CTransactionBuilderTestSetup : public TestChain100Setup auto locked_chain = chain->lock(); BOOST_CHECK(wallet->CreateTransaction(*locked_chain, {{GetScriptForDestination(tallyItem.txdest), nAmount, false}}, tx, nFeeRet, nChangePosRet, strError, coinControl)); } - CValidationState state; - BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, state)); + wallet->CommitTransaction(tx, {}, {}); AddTxToChain(tx->GetHash()); for (size_t n = 0; n < tx->vout.size(); ++n) { if (nChangePosRet != -1 && int(n) == nChangePosRet) { diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index f25d388b1eef..cd77b168bfe8 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -372,8 +371,7 @@ class ListCoinsTestingSetup : public TestChain100Setup 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); @@ -582,8 +580,7 @@ class CreateTransactionTestSetup : public TestChain100Setup std::string strError; CCoinControl coinControl; BOOST_CHECK(wallet->CreateTransaction(*wallet->chain().lock(), GetRecipients(vecEntries), tx, nFeeRet, nChangePosRet, strError, coinControl)); - CValidationState state; - BOOST_CHECK(wallet->CommitTransaction(tx, {}, {}, state)); + wallet->CommitTransaction(tx, {}, {}); CMutableTransaction blocktx; { LOCK(wallet->cs_wallet); @@ -924,8 +921,7 @@ BOOST_FIXTURE_TEST_CASE(select_coins_grouped_by_addresses, ListCoinsTestingSetup BOOST_CHECK(wallet->CreateTransaction(*locked_chain, {CRecipient{GetScriptForRawPubKey({}), 1 * COIN, true /* subtract fee */}}, tx2, fee, changePos, error, dummy)); } - CValidationState state; - BOOST_CHECK(wallet->CommitTransaction(tx1, {}, {}, state)); + wallet->CommitTransaction(tx1, {}, {}); BOOST_CHECK_EQUAL(wallet->GetAvailableBalance(), 0); CreateAndProcessBlock({CMutableTransaction(*tx2)}, GetScriptForRawPubKey({})); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9e584f6bcef9..4a30315d4701 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3992,55 +3992,47 @@ 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> orderForm, CValidationState& state) +void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector> orderForm) { - { - 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; - - 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); - - // Notify that old coins are spent - std::set updated_hahes; - for (const CTxIn& txin : wtxNew.tx->vin) - { - // notify only once - if(updated_hahes.find(txin.prevout.hash) != updated_hahes.end()) continue; - - CWalletTx &coin = mapWallet.at(txin.prevout.hash); - coin.BindWallet(this); - NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED); - updated_hahes.insert(txin.prevout.hash); - } - } + auto locked_chain = chain().lock(); + LOCK(cs_wallet); - // Get the inserted-CWalletTx from mapWallet so that the - // fInMempool flag is cached properly - CWalletTx& wtx = mapWallet.at(wtxNew.GetHash()); + 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 */ + // 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 + std::set updated_hahes; + for (const CTxIn& txin : wtxNew.tx->vin){ + // notify only once + if(updated_hahes.find(txin.prevout.hash) != updated_hahes.end()) continue; + + CWalletTx &coin = mapWallet.at(txin.prevout.hash); + coin.BindWallet(this); + NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED); + updated_hahes.insert(txin.prevout.hash); + } + // Get the inserted-CWalletTx from mapWallet so that the + // fInMempool flag is cached properly + CWalletTx& wtx = mapWallet.at(wtxNew.GetHash()); + + if (!fBroadcastTransactions) { + // Don't submit tx to the mempool + return; + } - 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. - } - } + 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) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 941e1e668207..9eb385bde0d7 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -994,7 +994,16 @@ class CWallet final : public CCryptoKeyStore, private interfaces::Chain::Notific */ bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign = true, int nExtraPayloadSize = 0); - bool CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector> 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> orderForm); bool DummySignTx(CMutableTransaction &txNew, const std::set &txouts, bool use_max_sig = false) const { diff --git a/test/functional/data/rpc_psbt.json b/test/functional/data/rpc_psbt.json index b2683d82b071..d831d225b782 100644 --- a/test/functional/data/rpc_psbt.json +++ b/test/functional/data/rpc_psbt.json @@ -17,7 +17,15 @@ "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wCAwABAAAAAAEAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAgAAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", - "cHNidP8BAHMCAAAAAbiWoY6pOQepFsEGhUPXaulX9rvye2NH+NrdlAHg+WgpAQAAAAD/////AkBLTAAAAAAAF6kUqWwXCcLM5BN2zoNqMNT5qMlIi7+HQEtMAAAAAAAXqRSVF/in2XNxAlN1OSxkyp0z+Wtg2YcAAAAAAAEBIBNssgAAAAAAF6kUamsvautR8hRlMRY6OKNTx03DK96HAQcXFgAUo8u1LWpHprjt/uENAwBpGZD0UH0BCGsCRzBEAiAONfH3DYiw67ZbylrsxCF/XXpVwyWBRgofyRbPslzvwgIgIKCsWw5sHSIPh1icNvcVLZLHWj6NA7Dk+4Os2pOnMbQBIQPGStfYHPtyhpV7zIWtn0Q4GXv5gK1zy/tnJ+cBXu4iiwABABYAFMwmJQEz+HDpBEEabxJ5PogPsqZRAAEAFgAUyCrGc3h3FYCmiIspbv2pSTKZ5jU" + "cHNidP8BAHMCAAAAAbiWoY6pOQepFsEGhUPXaulX9rvye2NH+NrdlAHg+WgpAQAAAAD/////AkBLTAAAAAAAF6kUqWwXCcLM5BN2zoNqMNT5qMlIi7+HQEtMAAAAAAAXqRSVF/in2XNxAlN1OSxkyp0z+Wtg2YcAAAAAAAEBIBNssgAAAAAAF6kUamsvautR8hRlMRY6OKNTx03DK96HAQcXFgAUo8u1LWpHprjt/uENAwBpGZD0UH0BCGsCRzBEAiAONfH3DYiw67ZbylrsxCF/XXpVwyWBRgofyRbPslzvwgIgIKCsWw5sHSIPh1icNvcVLZLHWj6NA7Dk+4Os2pOnMbQBIQPGStfYHPtyhpV7zIWtn0Q4GXv5gK1zy/tnJ+cBXu4iiwABABYAFMwmJQEz+HDpBEEabxJ5PogPsqZRAAEAFgAUyCrGc3h3FYCmiIspbv2pSTKZ5jU", + "cHNidP8BACoCAAAAAAFAQg8AAAAAABepFG6Rty1Vk+fUOR4v9E6R6YXDFkHwhwAAAAAAAQEAAQEBagA=", + "cHNidP8BACoCAAAAAAFAQg8AAAAAABepFG6Rty1Vk+fUOR4v9E6R6YXDFkHwhwAAAAAAAQAAAQABagA=", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJ//////////8AAQEJAADK/gAAAAAAAA==", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQMErd7f7gEDBAEAAAAA", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQQAAQQBagA=", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJAOH1BQAAAAAAAQUAAQUBUQA=", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQcAAQcBUQA=", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJAOH1BQAAAAAAAQgBAAEIAwEBUQA=" ], "valid" : [ "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA", diff --git a/test/lint/lint-spelling.ignore-words.txt b/test/lint/lint-spelling.ignore-words.txt index 8f2b4a341c12..3d652b7d7933 100644 --- a/test/lint/lint-spelling.ignore-words.txt +++ b/test/lint/lint-spelling.ignore-words.txt @@ -1,9 +1,7 @@ -cas hights mor mut objext -unselect useable setban wit @@ -19,3 +17,4 @@ unser crypted fo stoll +hist diff --git a/test/lint/lint-spelling.sh b/test/lint/lint-spelling.sh index 59803e745551..1d87310e10f9 100755 --- a/test/lint/lint-spelling.sh +++ b/test/lint/lint-spelling.sh @@ -15,6 +15,6 @@ if ! command -v codespell > /dev/null; then fi IGNORE_WORDS_FILE=test/lint/lint-spelling.ignore-words.txt -if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/crypto/" ":(exclude)src/leveldb/" ":(exclude)src/qt/locale/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/"); then +if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/crypto/" ":(exclude)src/leveldb/" ":(exclude)src/qt/locale/" ":(exclude)src/qt/*.qrc" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/"); then echo "^ Warning: codespell identified likely spelling errors. Any false positives? Add them to the list of ignored words in ${IGNORE_WORDS_FILE}" fi