mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-06-02 23:42:33 +02:00
Merge #13339: wallet: Replace %w by wallet name in -walletnotify script
4e9efac678
test: Check wallet name in -walletnotify script (João Barbosa)9a5b5ee81f
wallet: Replace %w by wallet name in -walletnotify script (João Barbosa) Pull request description: Fixes #13237. ACKs for top commit: laanwj: ACK4e9efac678
Tree-SHA512: 189dd1c785485f2e974d7c12531851b2a977778b3b954aa95efd527322ba3345924cfd587fb9c90b0fa979202af0ab2d90e53d125fe266a36c94f757e4176203
This commit is contained in:
commit
051439813e
@ -63,6 +63,7 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
@ -1047,6 +1048,15 @@ fs::path GetSpecialFolderPath(int nFolder, bool fCreate)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
std::string ShellEscape(const std::string& arg)
|
||||||
|
{
|
||||||
|
std::string escaped = arg;
|
||||||
|
boost::replace_all(escaped, "'", "'\"'\"'");
|
||||||
|
return "'" + escaped + "'";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if HAVE_SYSTEM
|
#if HAVE_SYSTEM
|
||||||
void runCommand(const std::string& strCommand)
|
void runCommand(const std::string& strCommand)
|
||||||
{
|
{
|
||||||
|
@ -81,6 +81,9 @@ fs::path GetConfigFile(const std::string& confPath);
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
|
fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef WIN32
|
||||||
|
std::string ShellEscape(const std::string& arg);
|
||||||
|
#endif
|
||||||
#if HAVE_SYSTEM
|
#if HAVE_SYSTEM
|
||||||
void runCommand(const std::string& strCommand);
|
void runCommand(const std::string& strCommand);
|
||||||
#endif
|
#endif
|
||||||
|
@ -62,7 +62,7 @@ void WalletInit::AddWalletOptions() const
|
|||||||
gArgs.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
|
gArgs.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
|
||||||
gArgs.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
|
gArgs.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
|
||||||
#if HAVE_SYSTEM
|
#if HAVE_SYSTEM
|
||||||
gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
|
gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes. %s in cmd is replaced by TxID and %w is replaced by wallet name. %w is not currently implemented on windows. On systems where %w is supported, it should NOT be quoted because this would break shell escaping used to invoke the command.", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
|
||||||
#endif
|
#endif
|
||||||
gArgs.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
|
gArgs.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
|
||||||
gArgs.AddArg("-zapwallettxes=<mode>", "Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup"
|
gArgs.AddArg("-zapwallettxes=<mode>", "Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup"
|
||||||
|
@ -847,6 +847,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
|||||||
if (!strCmd.empty())
|
if (!strCmd.empty())
|
||||||
{
|
{
|
||||||
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
|
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
|
||||||
|
#ifndef WIN32
|
||||||
|
// Substituting the wallet name isn't currently supported on windows
|
||||||
|
// because windows shell escaping has not been implemented yet:
|
||||||
|
// https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-537384875
|
||||||
|
// A few ways it could be implemented in the future are described in:
|
||||||
|
// https://github.com/bitcoin/bitcoin/pull/13339#issuecomment-461288094
|
||||||
|
boost::replace_all(strCmd, "%w", ShellEscape(GetName()));
|
||||||
|
#endif
|
||||||
std::thread t(runCommand, strCmd);
|
std::thread t(runCommand, strCmd);
|
||||||
t.detach(); // thread runs free
|
t.detach(); // thread runs free
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,16 @@ from test_framework.util import (
|
|||||||
connect_nodes,
|
connect_nodes,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Linux allow all characters other than \x00
|
||||||
|
# Windows disallow control characters (0-31) and /\?%:|"<>
|
||||||
|
FILE_CHAR_START = 32 if os.name == 'nt' else 1
|
||||||
|
FILE_CHAR_END = 128
|
||||||
|
FILE_CHAR_BLACKLIST = '/\\?%*:|"<>' if os.name == 'nt' else '/'
|
||||||
|
|
||||||
|
|
||||||
|
def notify_outputname(walletname, txid):
|
||||||
|
return txid if os.name == 'nt' else '{}_{}'.format(walletname, txid)
|
||||||
|
|
||||||
|
|
||||||
class NotificationsTest(BitcoinTestFramework):
|
class NotificationsTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
@ -20,6 +30,7 @@ class NotificationsTest(BitcoinTestFramework):
|
|||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
|
|
||||||
def setup_network(self):
|
def setup_network(self):
|
||||||
|
self.wallet = ''.join(chr(i) for i in range(FILE_CHAR_START, FILE_CHAR_END) if chr(i) not in FILE_CHAR_BLACKLIST)
|
||||||
self.alertnotify_dir = os.path.join(self.options.tmpdir, "alertnotify")
|
self.alertnotify_dir = os.path.join(self.options.tmpdir, "alertnotify")
|
||||||
self.blocknotify_dir = os.path.join(self.options.tmpdir, "blocknotify")
|
self.blocknotify_dir = os.path.join(self.options.tmpdir, "blocknotify")
|
||||||
self.walletnotify_dir = os.path.join(self.options.tmpdir, "walletnotify")
|
self.walletnotify_dir = os.path.join(self.options.tmpdir, "walletnotify")
|
||||||
@ -33,7 +44,8 @@ class NotificationsTest(BitcoinTestFramework):
|
|||||||
"-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))],
|
"-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))],
|
||||||
["-blockversion=211",
|
["-blockversion=211",
|
||||||
"-rescan",
|
"-rescan",
|
||||||
"-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, '%s'))]]
|
"-wallet={}".format(self.wallet),
|
||||||
|
"-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, notify_outputname('%w', '%s')))]]
|
||||||
super().setup_network()
|
super().setup_network()
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
@ -53,7 +65,7 @@ class NotificationsTest(BitcoinTestFramework):
|
|||||||
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
|
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
|
||||||
|
|
||||||
# directory content should equal the generated transaction hashes
|
# directory content should equal the generated transaction hashes
|
||||||
txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
|
txids_rpc = list(map(lambda t: notify_outputname(self.wallet, t['txid']), self.nodes[1].listtransactions("*", block_count)))
|
||||||
assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
|
assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
|
||||||
self.stop_node(1)
|
self.stop_node(1)
|
||||||
for tx_file in os.listdir(self.walletnotify_dir):
|
for tx_file in os.listdir(self.walletnotify_dir):
|
||||||
@ -67,7 +79,7 @@ class NotificationsTest(BitcoinTestFramework):
|
|||||||
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
|
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
|
||||||
|
|
||||||
# directory content should equal the generated transaction hashes
|
# directory content should equal the generated transaction hashes
|
||||||
txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
|
txids_rpc = list(map(lambda t: notify_outputname(self.wallet, t['txid']), self.nodes[1].listtransactions("*", block_count)))
|
||||||
assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
|
assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
|
||||||
|
|
||||||
# TODO: add test for `-alertnotify` large fork notifications
|
# TODO: add test for `-alertnotify` large fork notifications
|
||||||
|
Loading…
Reference in New Issue
Block a user