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 v18 vijay batch2 #4399

Merged
merged 5 commits into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/dash-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <memory>
#include <stdio.h>
#include <tuple>

#include <event2/buffer.h>
#include <event2/keyvalq_struct.h>
Expand Down Expand Up @@ -540,6 +541,10 @@ int main(int argc, char* argv[])
RegisterPrettyTerminateHander();
RegisterPrettySignalHandlers();

#ifdef WIN32
util::WinCmdLineArgs winArgs;
std::tie(argc, argv) = winArgs.get();
#endif
SetupEnvironment();
if (!SetupNetworking()) {
fprintf(stderr, "Error: Initializing networking failed\n");
Expand Down
4 changes: 4 additions & 0 deletions src/dashd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ int main(int argc, char* argv[])
RegisterPrettyTerminateHander();
RegisterPrettySignalHandlers();

#ifdef WIN32
util::WinCmdLineArgs winArgs;
std::tie(argc, argv) = winArgs.get();
#endif
SetupEnvironment();

// Connect dashd signal handlers
Expand Down
10 changes: 9 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,15 @@ void InitParameterInteraction()
// Warn if network-specific options (-addnode, -connect, etc) are
// specified in default section of config file, but not overridden
// on the command line or in this network's section of the config file.
gArgs.WarnForSectionOnlyArgs();
std::string network = gArgs.GetChainName();
for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) {
InitWarning(strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, network, network));
}

// Warn if unrecognized section name are present in the config file.
for (const auto& section : gArgs.GetUnrecognizedSections()) {
InitWarning(strprintf(_("Section [%s] is not recognized."), section));
}
}

static std::string ResolveErrMsg(const char * const optname, const std::string& strBind)
Expand Down
4 changes: 4 additions & 0 deletions src/qt/dash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,10 @@ int main(int argc, char *argv[])
RegisterPrettyTerminateHander();
RegisterPrettySignalHandlers();

#ifdef WIN32
util::WinCmdLineArgs winArgs;
std::tie(argc, argv) = winArgs.get();
#endif
SetupEnvironment();
util::ThreadRename("main");

Expand Down
1 change: 0 additions & 1 deletion src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listreceivedbyaddress", 1, "addlocked" },
{ "listreceivedbyaddress", 2, "include_empty" },
{ "listreceivedbyaddress", 3, "include_watchonly" },
{ "listreceivedbyaddress", 4, "address_filter" },
{ "listreceivedbyaccount", 0, "minconf" },
{ "listreceivedbyaccount", 1, "addlocked" },
{ "listreceivedbyaccount", 2, "include_empty" },
Expand Down
75 changes: 68 additions & 7 deletions src/util/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include <codecvt>

#include <io.h> /* for _commit */
#include <shellapi.h>
#include <shlobj.h>
#endif

Expand Down Expand Up @@ -399,15 +400,17 @@ ArgsManager::ArgsManager() :
// nothing to do
}

void ArgsManager::WarnForSectionOnlyArgs()
const std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
{
std::set<std::string> unsuitables;

LOCK(cs_args);

// if there's no section selected, don't worry
if (m_network.empty()) return;
if (m_network.empty()) return std::set<std::string> {};

// if it's okay to use the default section for this network, don't worry
if (m_network == CBaseChainParams::MAIN) return;
if (m_network == CBaseChainParams::MAIN) return std::set<std::string> {};

for (const auto& arg : m_network_only_args) {
std::pair<bool, std::string> found_result;
Expand All @@ -425,8 +428,29 @@ void ArgsManager::WarnForSectionOnlyArgs()
if (!found_result.first) continue;

// otherwise, issue a warning
LogPrintf("Warning: Config setting for %s only applied on %s network when in [%s] section.\n", arg, m_network, m_network);
unsuitables.insert(arg);
}
return unsuitables;
}


const std::set<std::string> ArgsManager::GetUnrecognizedSections() const
{
// Section names to be recognized in the config file.
static const std::set<std::string> available_sections{
CBaseChainParams::REGTEST,
CBaseChainParams::TESTNET,
CBaseChainParams::MAIN,
CBaseChainParams::DEVNET
};
std::set<std::string> diff;

LOCK(cs_args);
std::set_difference(
m_config_sections.begin(), m_config_sections.end(),
available_sections.begin(), available_sections.end(),
std::inserter(diff, diff.end()));
return diff;
}

void ArgsManager::SelectConfigNetwork(const std::string& network)
Expand Down Expand Up @@ -887,7 +911,7 @@ static std::string TrimString(const std::string& str, const std::string& pattern
return str.substr(front, end - front + 1);
}

static bool GetConfigOptions(std::istream& stream, std::string& error, std::vector<std::pair<std::string, std::string>> &options)
static bool GetConfigOptions(std::istream& stream, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::set<std::string>& sections)
{
std::string str, prefix;
std::string::size_type pos;
Expand All @@ -902,7 +926,9 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect
str = TrimString(str, pattern);
if (!str.empty()) {
if (*str.begin() == '[' && *str.rbegin() == ']') {
prefix = str.substr(1, str.size() - 2) + '.';
const std::string section = str.substr(1, str.size() - 2);
sections.insert(section);
prefix = section + '.';
} else if (*str.begin() == '-') {
error = strprintf("parse error on line %i: %s, options in configuration file must be specified without leading -", linenr, str);
return false;
Expand All @@ -914,6 +940,9 @@ static bool GetConfigOptions(std::istream& stream, std::string& error, std::vect
return false;
}
options.emplace_back(name, value);
if ((pos = name.rfind('.')) != std::string::npos) {
sections.insert(name.substr(0, pos));
}
} else {
error = strprintf("parse error on line %i: %s", linenr, str);
if (str.size() >= 2 && str.substr(0, 2) == "no") {
Expand All @@ -931,7 +960,8 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, boo
{
LOCK(cs_args);
std::vector<std::pair<std::string, std::string>> options;
if (!GetConfigOptions(stream, error, options)) {
m_config_sections.clear();
if (!GetConfigOptions(stream, error, options, m_config_sections)) {
return false;
}
for (const std::pair<std::string, std::string>& option : options) {
Expand Down Expand Up @@ -1298,6 +1328,10 @@ void SetupEnvironment()
} catch (const std::runtime_error&) {
setenv("LC_ALL", "C.UTF-8", 1);
}
#elif defined(WIN32)
// Set the default input/output charset is utf-8
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
#endif
// The path locale is lazy initialized and to avoid deinitialization errors
// in multithreading environments, it is set explicitly by the main thread.
Expand Down Expand Up @@ -1367,3 +1401,30 @@ int ScheduleBatchPriority()
return 1;
#endif
}

namespace util {
#ifdef WIN32
WinCmdLineArgs::WinCmdLineArgs()
{
wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf8_cvt;
argv = new char*[argc];
args.resize(argc);
for (int i = 0; i < argc; i++) {
args[i] = utf8_cvt.to_bytes(wargv[i]);
argv[i] = &*args[i].begin();
}
LocalFree(wargv);
}

WinCmdLineArgs::~WinCmdLineArgs()
{
delete[] argv;
}

std::pair<int, char**> WinCmdLineArgs::get()
{
return std::make_pair(argc, argv);
}
#endif
} // namespace util
24 changes: 23 additions & 1 deletion src/util/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include <boost/thread/condition_variable.hpp> // for boost::thread_interrupted
Expand Down Expand Up @@ -177,6 +178,7 @@ class ArgsManager
std::string m_network GUARDED_BY(cs_args);
std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
std::set<std::string> m_config_sections GUARDED_BY(cs_args);

[[nodiscard]] bool ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys = false);

Expand All @@ -197,7 +199,12 @@ class ArgsManager
* on the command line or in a network-specific section in the
* config file.
*/
void WarnForSectionOnlyArgs();
const std::set<std::string> GetUnsuitableSectionOnlyArgs() const;

/**
* Log warnings for unrecognized section names in the config file.
*/
const std::set<std::string> GetUnrecognizedSections() const;

/**
* Return a vector of strings of the given argument
Expand Down Expand Up @@ -397,6 +404,21 @@ inline void insert(std::set<TsetT>& dst, const Tsrc& src) {
dst.insert(src.begin(), src.end());
}

#ifdef WIN32
class WinCmdLineArgs
{
public:
WinCmdLineArgs();
~WinCmdLineArgs();
std::pair<int, char**> get();

private:
int argc;
char** argv;
std::vector<std::string> args;
};
#endif

} // namespace util

#endif // BITCOIN_UTIL_SYSTEM_H
2 changes: 1 addition & 1 deletion src/wallet/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
{
int64_t nStart = GetTimeMillis();
// Flush log data to the actual data file on all files that are not in use
LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: [%s] Flush(%s)%s\n", strPath, fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
if (!fDbEnvInit)
return;
{
Expand Down
5 changes: 5 additions & 0 deletions test/functional/feature_config_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ def test_config_file_parser(self):
conf.write('server=1\nrpcuser=someuser\nrpcpassword=some#pass')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')

with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('testnot.datadir=1\n[testnet]\n')
self.restart_node(0)
self.nodes[0].stop_node(expected_stderr='Warning: Section [testnet] is not recognized.' + os.linesep + 'Warning: Section [testnot] is not recognized.')

with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('') # clear

Expand Down
2 changes: 1 addition & 1 deletion test/functional/feature_uacomment.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def run_test(self):
self.nodes[0].assert_start_raises_init_error(["-uacomment=" + 'a' * 256], expected, match=ErrorMatch.FULL_REGEX)

self.log.info("test -uacomment unsafe characters")
for unsafe_char in ['/', ':', '(', ')']:
for unsafe_char in ['/', ':', '(', ')', '₿', '🏃']:
expected = "Error: User Agent comment \(" + re.escape(unsafe_char) + "\) contains unsafe characters."
self.nodes[0].assert_start_raises_init_error(["-uacomment=" + unsafe_char], expected, match=ErrorMatch.FULL_REGEX)

Expand Down
17 changes: 17 additions & 0 deletions test/functional/rpc_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@
from test_framework.test_framework import BitcoinTestFramework, is_zmq_enabled
from test_framework.util import assert_equal, assert_raises_rpc_error

import os


class HelpRpcTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1

def run_test(self):
self.test_categories()
self.dump_help()

def test_categories(self):
node = self.nodes[0]

# wrong argument count, note: Dash's help allows for two options since we utilize subcommands
Expand All @@ -33,5 +40,15 @@ def run_test(self):

assert_equal(titles, components)

def dump_help(self):
dump_dir = os.path.join(self.options.tmpdir, 'rpc_help_dump')
os.mkdir(dump_dir)
calls = [line.split(' ', 1)[0] for line in self.nodes[0].help().splitlines() if line and not line.startswith('==')]
for call in calls:
with open(os.path.join(dump_dir, call), 'w', encoding='utf-8') as f:
# Make sure the node can generate the help at runtime without crashing
f.write(self.nodes[0].help(call))


if __name__ == '__main__':
HelpRpcTest().main()
4 changes: 4 additions & 0 deletions test/functional/wallet_listreceivedby.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ def run_test(self):
res = self.nodes[1].listreceivedbyaddress(minconf=0, addlocked=False, include_empty=True, include_watchonly=True, address_filter=addr)
assert_array_result(res, {"address": addr}, expected)
assert_equal(len(res), 1)
# Test for regression on CLI calls with address string (#14173)
cli_res = self.nodes[1].cli.listreceivedbyaddress(0, True, True, True, addr)
assert_array_result(cli_res, {"address": addr}, expected)
assert_equal(len(cli_res), 1)
# Error on invalid address
assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, addlocked=True, include_empty=True, include_watchonly=True, address_filter="bamboozling")
# Another address receive money
Expand Down