Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport: bitcoin#21178, #22089, #22130, #22210, #22216, bitcoin-core/gui#361, partial: bitcoin#14123 #6234

Merged
merged 7 commits into from
Sep 3, 2024
2 changes: 1 addition & 1 deletion src/bitcoind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ static bool AppInit(NodeContext& node, int argc, char* argv[])
util::ThreadSetInternalName("init");

// If Qt is used, parameters/dash.conf are parsed in qt/bitcoin.cpp's main()
SetupServerArgs(node);
ArgsManager& args = *Assert(node.args);
SetupServerArgs(args);
std::string error;
if (!args.ParseParameters(argc, argv, error)) {
return InitError(Untranslated(strprintf("Error parsing command line arguments: %s\n", error)));
Expand Down
6 changes: 1 addition & 5 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,12 +484,8 @@ std::string GetSupportedSocketEventsStr()
return strSupportedModes;
}

void SetupServerArgs(NodeContext& node)
void SetupServerArgs(ArgsManager& argsman)
{
assert(!node.args);
node.args = &gArgs;
ArgsManager& argsman = *node.args;

SetupHelpOptions(argsman);
argsman.AddArg("-help-debug", "Print help message with debugging options and exit", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);

Expand Down
2 changes: 1 addition & 1 deletion src/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void PrepareShutdown(NodeContext& node);
/**
* Register all arguments with the ArgsManager
*/
void SetupServerArgs(NodeContext& node);
void SetupServerArgs(ArgsManager& argsman);

/** Returns licensing information (for -version) */
std::string LicenseInfo();
Expand Down
2 changes: 2 additions & 0 deletions src/init/bitcoin-node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <interfaces/init.h>
#include <interfaces/ipc.h>
#include <node/context.h>
#include <util/system.h>

#include <memory>

Expand All @@ -20,6 +21,7 @@ class BitcoinNodeInit : public interfaces::Init
: m_node(node),
m_ipc(interfaces::MakeIpc(EXE_NAME, arg0, *this))
{
m_node.args = &gArgs;
m_node.init = this;
}
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
Expand Down
2 changes: 2 additions & 0 deletions src/init/bitcoind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <interfaces/init.h>
#include <node/context.h>
#include <util/system.h>

#include <memory>

Expand All @@ -14,6 +15,7 @@ class BitcoindInit : public interfaces::Init
public:
BitcoindInit(NodeContext& node) : m_node(node)
{
m_node.args = &gArgs;
m_node.init = this;
}
NodeContext& m_node;
Expand Down
3 changes: 2 additions & 1 deletion src/qt/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,8 @@ int GuiMain(int argc, char* argv[])

/// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
// Command-line options take precedence:
SetupServerArgs(node_context);
node_context.args = &gArgs;
SetupServerArgs(gArgs);
SetupUIArgs(gArgs);
std::string error;
if (!gArgs.ParseParameters(argc, argv, error)) {
Expand Down
22 changes: 11 additions & 11 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,9 @@ void BitcoinGUI::createActions()
#ifdef ENABLE_WALLET
// These showNormalIfMinimized are needed because Send Coins and Receive Coins
// can be triggered from the tray menu, and need to show the GUI to be useful.
connect(sendCoinsMenuAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
connect(coinJoinCoinsMenuAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
connect(receiveCoinsMenuAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
connect(sendCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(coinJoinCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(receiveCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(sendCoinsMenuAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
connect(coinJoinCoinsMenuAction, &QAction::triggered, [this]{ gotoCoinJoinCoinsPage(); });
connect(receiveCoinsMenuAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
Expand Down Expand Up @@ -506,11 +506,11 @@ void BitcoinGUI::createActions()
connect(changePassphraseAction, &QAction::triggered, walletFrame, &WalletFrame::changePassphrase);
connect(unlockWalletAction, &QAction::triggered, walletFrame, &WalletFrame::unlockWallet);
connect(lockWalletAction, &QAction::triggered, walletFrame, &WalletFrame::lockWallet);
connect(signMessageAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
connect(signMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(signMessageAction, &QAction::triggered, [this]{ gotoSignMessageTab(); });
connect(m_load_psbt_action, &QAction::triggered, [this]{ gotoLoadPSBT(); });
connect(m_load_psbt_clipboard_action, &QAction::triggered, [this]{ gotoLoadPSBT(true); });
connect(verifyMessageAction, &QAction::triggered, this, static_cast<void (BitcoinGUI::*)()>(&BitcoinGUI::showNormalIfMinimized));
connect(verifyMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(verifyMessageAction, &QAction::triggered, [this]{ gotoVerifyMessageTab(); });
connect(usedSendingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedSendingAddresses);
connect(usedReceivingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedReceivingAddresses);
Expand Down Expand Up @@ -730,7 +730,7 @@ void BitcoinGUI::createToolBars()
connect(historyButton, &QToolButton::clicked, this, &BitcoinGUI::gotoHistoryPage);

// Give the selected tab button a bolder font.
connect(tabGroup, static_cast<void (QButtonGroup::*)(QAbstractButton *, bool)>(&QButtonGroup::buttonToggled), this, &BitcoinGUI::highlightTabButton);
connect(tabGroup, qOverload<QAbstractButton *, bool>(&QButtonGroup::buttonToggled), this, &BitcoinGUI::highlightTabButton);

for (auto button : tabGroup->buttons()) {
GUIUtil::setFont({button}, GUIUtil::FontWeight::Normal, 16);
Expand Down Expand Up @@ -799,7 +799,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
// Note: ignore this on Mac - this is not the way tray should work there
connect(trayIcon, &QSystemTrayIcon::activated, this, &BitcoinGUI::trayIconActivated);
#else
// Note: On Mac, the dock icon is also used to provide menu functionality
// Note: on macOS, the Dock icon is also used to provide menu functionality
// similar to one for tray icon
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, this, &BitcoinGUI::macosDockIconActivated);
Expand Down Expand Up @@ -1019,7 +1019,7 @@ void BitcoinGUI::createIconMenu(QMenu *pmenu)
{
// Configuration of the tray icon (or dock icon) icon menu
#ifndef Q_OS_MAC
// Note: On Mac, the dock icon's menu already has show / hide action.
// Note: On macOS, the Dock icon is used to provide the tray's functionality.
trayIconMenu->addAction(toggleHideAction);
trayIconMenu->addSeparator();
#endif
Expand All @@ -1045,7 +1045,7 @@ void BitcoinGUI::createIconMenu(QMenu *pmenu)
if (enableWallet) {
pmenu->addAction(showBackupsAction);
}
#ifndef Q_OS_MAC // This is built-in on Mac
#ifndef Q_OS_MAC // This is built-in on macOS
pmenu->addSeparator();
pmenu->addAction(quitAction);
#endif
Expand Down Expand Up @@ -1617,7 +1617,7 @@ void BitcoinGUI::message(const QString& title, QString message, unsigned int sty
void BitcoinGUI::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
#ifndef Q_OS_MAC // Ignored on Mac
#ifndef Q_OS_MAC // Ignored on macOS
if(e->type() == QEvent::WindowStateChange)
{
if(clientModel && clientModel->getOptionsModel() && clientModel->getOptionsModel()->getMinimizeToTray())
Expand Down Expand Up @@ -1649,7 +1649,7 @@ void BitcoinGUI::changeEvent(QEvent *e)

void BitcoinGUI::closeEvent(QCloseEvent *event)
{
#ifndef Q_OS_MAC // Ignored on Mac
#ifndef Q_OS_MAC // Ignored on macOS
if(clientModel && clientModel->getOptionsModel())
{
if(!clientModel->getOptionsModel()->getMinimizeOnClose())
Expand Down
3 changes: 2 additions & 1 deletion src/test/util/setup_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
: m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME / g_insecure_rand_ctx_temp_path.rand256().ToString()},
m_args{}
{
m_node.args = &gArgs;
const std::vector<const char*> arguments = Cat(
{
"dummy",
Expand All @@ -157,7 +158,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
gArgs.ForceSetArg("-datadir", fs::PathToString(m_path_root));
gArgs.ClearPathCache();
{
SetupServerArgs(m_node);
SetupServerArgs(*m_node.args);
std::string error;
const bool success{m_node.args->ParseParameters(arguments.size(), arguments.data(), error)};
assert(success);
Expand Down
43 changes: 15 additions & 28 deletions test/functional/mempool_package_onemore.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@

from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error, satoshi_round
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
chain_transaction,
)

MAX_ANCESTORS = 25
MAX_DESCENDANTS = 25
Expand All @@ -24,23 +28,6 @@ def set_test_params(self):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

# Build a transaction that spends parent_txid:vout
# Return amount sent
def chain_transaction(self, node, parent_txids, vouts, value, fee, num_outputs):
send_value = satoshi_round((value - fee)/num_outputs)
inputs = []
for (txid, vout) in zip(parent_txids, vouts):
inputs.append({'txid' : txid, 'vout' : vout})
outputs = {}
for _ in range(num_outputs):
outputs[node.getnewaddress()] = send_value
rawtx = node.createrawtransaction(inputs, outputs)
signedtx = node.signrawtransactionwithwallet(rawtx)
txid = node.sendrawtransaction(signedtx['hex'])
fulltx = node.getrawtransaction(txid, 1)
assert len(fulltx['vout']) == num_outputs # make sure we didn't generate a change output
return (txid, send_value)

def run_test(self):
# Mine some blocks and have them mature.
self.nodes[0].generate(COINBASE_MATURITY + 1)
Expand All @@ -53,32 +40,32 @@ def run_test(self):
# MAX_ANCESTORS transactions off a confirmed tx should be fine
chain = []
for _ in range(4):
(txid, sent_value) = self.chain_transaction(self.nodes[0], [txid], [vout], value, fee, 2)
(txid, sent_value) = chain_transaction(self.nodes[0], [txid], [vout], value, fee, 2)
vout = 0
value = sent_value
chain.append([txid, value])
for _ in range(MAX_ANCESTORS - 4):
(txid, sent_value) = self.chain_transaction(self.nodes[0], [txid], [0], value, fee, 1)
(txid, sent_value) = chain_transaction(self.nodes[0], [txid], [0], value, fee, 1)
value = sent_value
chain.append([txid, value])
(second_chain, second_chain_value) = self.chain_transaction(self.nodes[0], [utxo[1]['txid']], [utxo[1]['vout']], utxo[1]['amount'], fee, 1)
(second_chain, second_chain_value) = chain_transaction(self.nodes[0], [utxo[1]['txid']], [utxo[1]['vout']], utxo[1]['amount'], fee, 1)

# Check mempool has MAX_ANCESTORS + 1 transactions in it
assert_equal(len(self.nodes[0].getrawmempool(True)), MAX_ANCESTORS + 1)

# Adding one more transaction on to the chain should fail.
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many unconfirmed ancestors [limit: 25]", self.chain_transaction, self.nodes[0], [txid], [0], value, fee, 1)
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many unconfirmed ancestors [limit: 25]", chain_transaction, self.nodes[0], [txid], [0], value, fee, 1)
# ...even if it chains on from some point in the middle of the chain.
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, self.nodes[0], [chain[2][0]], [1], chain[2][1], fee, 1)
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, self.nodes[0], [chain[1][0]], [1], chain[1][1], fee, 1)
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", chain_transaction, self.nodes[0], [chain[2][0]], [1], chain[2][1], fee, 1)
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", chain_transaction, self.nodes[0], [chain[1][0]], [1], chain[1][1], fee, 1)
# ...even if it chains on to two parent transactions with one in the chain.
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, self.nodes[0], [chain[0][0], second_chain], [1, 0], chain[0][1] + second_chain_value, fee, 1)
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", chain_transaction, self.nodes[0], [chain[0][0], second_chain], [1, 0], chain[0][1] + second_chain_value, fee, 1)
# ...especially if its > 40k weight
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 350)
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", chain_transaction, self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 350)
# But not if it chains directly off the first transaction
self.chain_transaction(self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 1)
chain_transaction(self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 1)
# and the second chain should work just fine
self.chain_transaction(self.nodes[0], [second_chain], [0], second_chain_value, fee, 1)
chain_transaction(self.nodes[0], [second_chain], [0], second_chain_value, fee, 1)

# Finally, check that we added two transactions
assert_equal(len(self.nodes[0].getrawmempool(True)), MAX_ANCESTORS + 3)
Expand Down
30 changes: 8 additions & 22 deletions test/functional/mempool_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
chain_transaction,
satoshi_round,
)

Expand Down Expand Up @@ -42,21 +43,6 @@ def set_test_params(self):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

# Build a transaction that spends parent_txid:vout
# Return amount sent
def chain_transaction(self, node, parent_txid, vout, value, fee, num_outputs):
send_value = satoshi_round((value - fee)/num_outputs)
inputs = [ {'txid' : parent_txid, 'vout' : vout} ]
outputs = {}
for _ in range(num_outputs):
outputs[node.getnewaddress()] = send_value
rawtx = node.createrawtransaction(inputs, outputs)
signedtx = node.signrawtransactionwithwallet(rawtx)
txid = node.sendrawtransaction(signedtx['hex'])
fulltx = node.getrawtransaction(txid, 1)
assert len(fulltx['vout']) == num_outputs # make sure we didn't generate a change output
return (txid, send_value)

def run_test(self):
# Mine some blocks and have them mature.
peer_inv_store = self.nodes[0].add_p2p_connection(P2PTxInvStore()) # keep track of invs
Expand All @@ -70,7 +56,7 @@ def run_test(self):
# MAX_ANCESTORS transactions off a confirmed tx should be fine
chain = []
for _ in range(MAX_ANCESTORS):
(txid, sent_value) = self.chain_transaction(self.nodes[0], txid, 0, value, fee, 1)
(txid, sent_value) = chain_transaction(self.nodes[0], [txid], [0], value, fee, 1)
value = sent_value
chain.append(txid)

Expand Down Expand Up @@ -184,7 +170,7 @@ def run_test(self):
assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN + 1000)

# Adding one more transaction on to the chain should fail.
assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], txid, vout, value, fee, 1)
assert_raises_rpc_error(-26, "too-long-mempool-chain", chain_transaction, self.nodes[0], [txid], [vout], value, fee, 1)

# Check that prioritising a tx before it's added to the mempool works
# First clear the mempool by mining a block.
Expand Down Expand Up @@ -233,7 +219,7 @@ def run_test(self):
transaction_package = []
tx_children = []
# First create one parent tx with 10 children
(txid, sent_value) = self.chain_transaction(self.nodes[0], txid, vout, value, fee, 10)
(txid, sent_value) = chain_transaction(self.nodes[0], [txid], [vout], value, fee, 10)
parent_transaction = txid
for i in range(10):
transaction_package.append({'txid': txid, 'vout': i, 'amount': sent_value})
Expand All @@ -242,7 +228,7 @@ def run_test(self):
chain = [] # save sent txs for the purpose of checking node1's mempool later (see below)
for _ in range(MAX_DESCENDANTS - 1):
utxo = transaction_package.pop(0)
(txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10)
(txid, sent_value) = chain_transaction(self.nodes[0], [utxo['txid']], [utxo['vout']], utxo['amount'], fee, 10)
chain.append(txid)
if utxo['txid'] is parent_transaction:
tx_children.append(txid)
Expand All @@ -258,7 +244,7 @@ def run_test(self):

# Sending one more chained transaction will fail
utxo = transaction_package.pop(0)
assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10)
assert_raises_rpc_error(-26, "too-long-mempool-chain", chain_transaction, self.nodes[0], [utxo['txid']], [utxo['vout']], utxo['amount'], fee, 10)

# Check that node1's mempool is as expected, containing:
# - txs from previous ancestor test (-> custom ancestor limit)
Expand Down Expand Up @@ -316,13 +302,13 @@ def run_test(self):
value = send_value

# Create tx1
tx1_id, _ = self.chain_transaction(self.nodes[0], tx0_id, 0, value, fee, 1)
tx1_id, _ = chain_transaction(self.nodes[0], [tx0_id], [0], value, fee, 1)

# Create tx2-7
vout = 1
txid = tx0_id
for _ in range(6):
(txid, sent_value) = self.chain_transaction(self.nodes[0], txid, vout, value, fee, 1)
(txid, sent_value) = chain_transaction(self.nodes[0], [txid], [vout], value, fee, 1)
vout = 0
value = sent_value

Expand Down
Loading
Loading