mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
Merge pull request #4215 from PastaPastaPasta/backports-0.18-triv
backport: 'trivial' pr1
This commit is contained in:
commit
d5e432a278
20
configure.ac
20
configure.ac
@ -357,7 +357,14 @@ if test x$use_sanitizers != x; then
|
||||
AX_CHECK_LINK_FLAG(
|
||||
[[-fsanitize=$use_sanitizers]],
|
||||
[[SANITIZER_LDFLAGS=-fsanitize=$use_sanitizers]],
|
||||
[AC_MSG_ERROR([linker did not accept requested flags, you are missing required libraries])])
|
||||
[AC_MSG_ERROR([linker did not accept requested flags, you are missing required libraries])],
|
||||
[],
|
||||
[AC_LANG_PROGRAM([[
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { return 0; }
|
||||
__attribute__((weak)) // allow for libFuzzer linking
|
||||
]],[[]])])
|
||||
fi
|
||||
|
||||
ERROR_CXXFLAGS=
|
||||
@ -578,17 +585,6 @@ case $host in
|
||||
LEVELDB_TARGET_FLAGS="-DOS_MACOSX"
|
||||
if test x$cross_compiling != xyes; then
|
||||
BUILD_OS=darwin
|
||||
AC_CHECK_PROG([PORT],port, port)
|
||||
if test x$PORT = xport; then
|
||||
dnl add default macports paths
|
||||
CPPFLAGS="$CPPFLAGS -isystem /opt/local/include"
|
||||
LIBS="$LIBS -L/opt/local/lib"
|
||||
if test -d /opt/local/include/db48; then
|
||||
CPPFLAGS="$CPPFLAGS -I/opt/local/include/db48"
|
||||
LIBS="$LIBS -L/opt/local/lib/db48"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_PATH_PROGS([RSVG_CONVERT], [rsvg-convert rsvg],rsvg-convert)
|
||||
AC_CHECK_PROG([BREW],brew, brew)
|
||||
if test x$BREW = xbrew; then
|
||||
|
@ -52,15 +52,22 @@ def applies_to_file(filename):
|
||||
# obtain list of files in repo according to INCLUDE and EXCLUDE
|
||||
################################################################################
|
||||
|
||||
GIT_LS_CMD = 'git ls-files'
|
||||
GIT_LS_CMD = 'git ls-files --full-name'.split(' ')
|
||||
GIT_TOPLEVEL_CMD = 'git rev-parse --show-toplevel'.split(' ')
|
||||
|
||||
def call_git_ls():
|
||||
out = subprocess.check_output(GIT_LS_CMD.split(' '))
|
||||
def call_git_ls(base_directory):
|
||||
out = subprocess.check_output([*GIT_LS_CMD, base_directory])
|
||||
return [f for f in out.decode("utf-8").split('\n') if f != '']
|
||||
|
||||
def get_filenames_to_examine():
|
||||
filenames = call_git_ls()
|
||||
return sorted([filename for filename in filenames if
|
||||
def call_git_toplevel():
|
||||
"Returns the absolute path to the project root"
|
||||
return subprocess.check_output(GIT_TOPLEVEL_CMD).strip().decode("utf-8")
|
||||
|
||||
def get_filenames_to_examine(base_directory):
|
||||
"Returns an array of absolute paths to any project files in the base_directory that pass the include/exclude filters"
|
||||
root = call_git_toplevel()
|
||||
filenames = call_git_ls(base_directory)
|
||||
return sorted([os.path.join(root, filename) for filename in filenames if
|
||||
applies_to_file(filename)])
|
||||
|
||||
################################################################################
|
||||
@ -87,24 +94,12 @@ def compile_copyright_regex(copyright_style, year_style, name):
|
||||
EXPECTED_HOLDER_NAMES = [
|
||||
"Satoshi Nakamoto\n",
|
||||
"The Bitcoin Core developers\n",
|
||||
"The Bitcoin Core developers \n",
|
||||
"Bitcoin Core Developers\n",
|
||||
"the Bitcoin Core developers\n",
|
||||
"The Bitcoin developers\n",
|
||||
"The LevelDB Authors\. All rights reserved\.\n",
|
||||
"BitPay Inc\.\n",
|
||||
"BitPay, Inc\.\n",
|
||||
"University of Illinois at Urbana-Champaign\.\n",
|
||||
"MarcoFalke\n",
|
||||
"Pieter Wuille\n",
|
||||
"Pieter Wuille +\*\n",
|
||||
"Pieter Wuille, Gregory Maxwell +\*\n",
|
||||
"Pieter Wuille, Andrew Poelstra +\*\n",
|
||||
"Andrew Poelstra +\*\n",
|
||||
"Wladimir J. van der Laan\n",
|
||||
"Jeff Garzik\n",
|
||||
"Diederik Huys, Pieter Wuille +\*\n",
|
||||
"Thomas Daede, Cory Fields +\*\n",
|
||||
"Jan-Klaas Kollhof\n",
|
||||
"Sam Rushing\n",
|
||||
"ArtForz -- public domain half-a-node\n",
|
||||
@ -148,7 +143,7 @@ def file_has_without_c_style_copyright_for_holder(contents, holder_name):
|
||||
################################################################################
|
||||
|
||||
def read_file(filename):
|
||||
return open(os.path.abspath(filename), 'r', encoding="utf8").read()
|
||||
return open(filename, 'r', encoding="utf8").read()
|
||||
|
||||
def gather_file_info(filename):
|
||||
info = {}
|
||||
@ -262,12 +257,9 @@ def print_report(file_infos, verbose):
|
||||
print(SEPARATOR)
|
||||
|
||||
def exec_report(base_directory, verbose):
|
||||
original_cwd = os.getcwd()
|
||||
os.chdir(base_directory)
|
||||
filenames = get_filenames_to_examine()
|
||||
filenames = get_filenames_to_examine(base_directory)
|
||||
file_infos = [gather_file_info(f) for f in filenames]
|
||||
print_report(file_infos, verbose)
|
||||
os.chdir(original_cwd)
|
||||
|
||||
################################################################################
|
||||
# report cmd
|
||||
@ -327,13 +319,13 @@ def get_most_recent_git_change_year(filename):
|
||||
################################################################################
|
||||
|
||||
def read_file_lines(filename):
|
||||
f = open(os.path.abspath(filename), 'r', encoding="utf8")
|
||||
f = open(filename, 'r', encoding="utf8")
|
||||
file_lines = f.readlines()
|
||||
f.close()
|
||||
return file_lines
|
||||
|
||||
def write_file_lines(filename, file_lines):
|
||||
f = open(os.path.abspath(filename), 'w', encoding="utf8")
|
||||
f = open(filename, 'w', encoding="utf8")
|
||||
f.write(''.join(file_lines))
|
||||
f.close()
|
||||
|
||||
@ -401,11 +393,8 @@ def update_updatable_copyright(filename):
|
||||
"Copyright updated! -> %s" % last_git_change_year)
|
||||
|
||||
def exec_update_header_year(base_directory):
|
||||
original_cwd = os.getcwd()
|
||||
os.chdir(base_directory)
|
||||
for filename in get_filenames_to_examine():
|
||||
for filename in get_filenames_to_examine(base_directory):
|
||||
update_updatable_copyright(filename)
|
||||
os.chdir(original_cwd)
|
||||
|
||||
################################################################################
|
||||
# update cmd
|
||||
|
@ -172,12 +172,6 @@ class DeploymentInfo(object):
|
||||
if os.path.exists(os.path.join(parentDir, "translations")):
|
||||
# Classic layout, e.g. "/usr/local/Trolltech/Qt-4.x.x"
|
||||
self.qtPath = parentDir
|
||||
elif os.path.exists(os.path.join(parentDir, "share", "qt4", "translations")):
|
||||
# MacPorts layout, e.g. "/opt/local/share/qt4"
|
||||
self.qtPath = os.path.join(parentDir, "share", "qt4")
|
||||
elif os.path.exists(os.path.join(os.path.dirname(parentDir), "share", "qt4", "translations")):
|
||||
# Newer Macports layout
|
||||
self.qtPath = os.path.join(os.path.dirname(parentDir), "share", "qt4")
|
||||
else:
|
||||
self.qtPath = os.getenv("QTDIR", None)
|
||||
|
||||
|
@ -11,6 +11,7 @@ $(package)_config_opts_mingw32=--enable-mingw
|
||||
$(package)_config_opts_linux=--with-pic
|
||||
$(package)_cflags+=-Wno-error=implicit-function-declaration
|
||||
$(package)_cxxflags=-std=c++11
|
||||
$(package)_cppflags_mingw32=-DUNICODE -D_UNICODE
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
|
@ -20,6 +20,7 @@ For full TX query capability, one must enable the transaction index via "txindex
|
||||
`GET /rest/block/notxdetails/<BLOCK-HASH>.<bin|hex|json>`
|
||||
|
||||
Given a block hash: returns a block, in binary, hex-encoded binary or JSON formats.
|
||||
Responds with 404 if the block doesn't exist.
|
||||
|
||||
The HTTP request and response are both handled entirely in-memory, thus making maximum memory usage at least 2.66MB (1 MB max block, plus hex encoding) per request.
|
||||
|
||||
@ -29,6 +30,12 @@ With the /notxdetails/ option JSON response will only contain the transaction ha
|
||||
`GET /rest/headers/<COUNT>/<BLOCK-HASH>.<bin|hex|json>`
|
||||
|
||||
Given a block hash: returns <COUNT> amount of blockheaders in upward direction.
|
||||
Returns empty if the block doesn't exist or it isn't in the active chain.
|
||||
|
||||
#### Blockhash by height
|
||||
`GET /rest/blockhashbyheight/<HEIGHT>.<bin|hex|json>`
|
||||
|
||||
Given a height: returns hash of block in best-block-chain at height provided.
|
||||
|
||||
#### Chaininfos
|
||||
`GET /rest/chaininfo.json`
|
||||
|
@ -7,8 +7,8 @@ Developer Notes
|
||||
- [Developer Notes](#developer-notes)
|
||||
- [Coding Style (General)](#coding-style-general)
|
||||
- [Coding Style (C++)](#coding-style-c)
|
||||
- [Doxygen comments](#doxygen-comments)
|
||||
- [Coding Style (Python)](#coding-style-python)
|
||||
- [Coding Style (Doxygen-compatible comments)](#coding-style-doxygen-compatible-comments)
|
||||
- [Development tips and tricks](#development-tips-and-tricks)
|
||||
- [Compiling for debugging](#compiling-for-debugging)
|
||||
- [Compiling for gprof profiling](#compiling-for-gprof-profiling)
|
||||
@ -119,10 +119,17 @@ public:
|
||||
} // namespace foo
|
||||
```
|
||||
|
||||
Doxygen comments
|
||||
-----------------
|
||||
Coding Style (Python)
|
||||
---------------------
|
||||
|
||||
To facilitate the generation of documentation, use doxygen-compatible comment blocks for functions, methods and fields.
|
||||
Refer to [/test/functional/README.md#style-guidelines](/test/functional/README.md#style-guidelines).
|
||||
|
||||
Coding Style (Doxygen-compatible comments)
|
||||
------------------------------------------
|
||||
|
||||
Dash Core uses [Doxygen](http://www.doxygen.nl/) to generate its official documentation.
|
||||
|
||||
Use Doxygen-compatible comment blocks for functions, methods, and fields.
|
||||
|
||||
For example, to describe a function use:
|
||||
```c++
|
||||
@ -155,7 +162,7 @@ int var; //!< Detailed description after the member
|
||||
```
|
||||
|
||||
or
|
||||
```cpp
|
||||
```c++
|
||||
//! Description before the member
|
||||
int var;
|
||||
```
|
||||
@ -175,15 +182,15 @@ Not OK (used plenty in the current source, but not picked up):
|
||||
//
|
||||
```
|
||||
|
||||
A full list of comment syntaxes picked up by doxygen can be found at http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html,
|
||||
but if possible use one of the above styles.
|
||||
A full list of comment syntaxes picked up by Doxygen can be found at https://www.stack.nl/~dimitri/doxygen/manual/docblocks.html,
|
||||
but the above styles are favored.
|
||||
|
||||
Documentation can be generated with `make docs` and cleaned up with `make clean-docs`.
|
||||
Documentation can be generated with `make docs` and cleaned up with `make clean-docs`. The resulting files are located in `doc/doxygen/html`; open `index.html` to view the homepage.
|
||||
|
||||
Coding Style (Python)
|
||||
---------------------
|
||||
|
||||
Refer to [/test/functional/README.md#style-guidelines](/test/functional/README.md#style-guidelines).
|
||||
Before running `make docs`, you will need to install dependencies `doxygen` and `dot`. For example, on MacOS via Homebrew:
|
||||
```
|
||||
brew install doxygen --with-graphviz
|
||||
```
|
||||
|
||||
Development tips and tricks
|
||||
---------------------------
|
||||
|
@ -3,10 +3,11 @@ Fuzz-testing Dash Core
|
||||
|
||||
A special test harness `test_dash_fuzzy` is provided to provide an easy
|
||||
entry point for fuzzers and the like. In this document we'll describe how to
|
||||
use it with AFL.
|
||||
use it with AFL and libFuzzer.
|
||||
|
||||
Building AFL
|
||||
-------------
|
||||
## AFL
|
||||
|
||||
### Building AFL
|
||||
|
||||
It is recommended to always use the latest version of afl:
|
||||
```
|
||||
@ -17,8 +18,7 @@ make
|
||||
export AFLPATH=$PWD
|
||||
```
|
||||
|
||||
Instrumentation
|
||||
----------------
|
||||
### Instrumentation
|
||||
|
||||
To build Dash Core using AFL instrumentation (this assumes that the
|
||||
`AFLPATH` was set as above):
|
||||
@ -39,8 +39,7 @@ compiling using `afl-clang-fast`/`afl-clang-fast++` the resulting
|
||||
features "persistent mode" and "deferred forkserver" can be used. See
|
||||
https://github.com/mcarpenter/afl/tree/master/llvm_mode for details.
|
||||
|
||||
Preparing fuzzing
|
||||
------------------
|
||||
### Preparing fuzzing
|
||||
|
||||
AFL needs an input directory with examples, and an output directory where it
|
||||
will place examples that it found. These can be anywhere in the file system,
|
||||
@ -60,8 +59,7 @@ Example inputs are available from:
|
||||
|
||||
Extract these (or other starting inputs) into the `inputs` directory before starting fuzzing.
|
||||
|
||||
Fuzzing
|
||||
--------
|
||||
### Fuzzing
|
||||
|
||||
To start the actual fuzzing use:
|
||||
```
|
||||
@ -70,3 +68,21 @@ $AFLPATH/afl-fuzz -i ${AFLIN} -o ${AFLOUT} -m52 -- test/test_dash_fuzzy
|
||||
|
||||
You may have to change a few kernel parameters to test optimally - `afl-fuzz`
|
||||
will print an error and suggestion if so.
|
||||
|
||||
## libFuzzer
|
||||
|
||||
A recent version of `clang`, the address sanitizer and libFuzzer is needed (all
|
||||
found in the `compiler-rt` runtime libraries package).
|
||||
|
||||
To build the `test/test_dash_fuzzy` executable run
|
||||
|
||||
```
|
||||
./configure --disable-ccache --with-sanitizers=fuzzer,address CC=clang CXX=clang++
|
||||
make
|
||||
```
|
||||
|
||||
The fuzzer needs some inputs to work on, but the inputs or seeds can be used
|
||||
interchangeably between libFuzzer and AFL.
|
||||
|
||||
See https://llvm.org/docs/LibFuzzer.html#running on how to run the libFuzzer
|
||||
instrumented executable.
|
||||
|
10
src/init.cpp
10
src/init.cpp
@ -1253,7 +1253,7 @@ bool AppInitParameterInteraction()
|
||||
|
||||
// also see: InitParameterInteraction()
|
||||
|
||||
if (!fs::is_directory(GetBlocksDir(false))) {
|
||||
if (!fs::is_directory(GetBlocksDir())) {
|
||||
return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str()));
|
||||
}
|
||||
|
||||
@ -2420,8 +2420,14 @@ bool AppInitMain()
|
||||
|
||||
// ********************************************************* Step 11: import blocks
|
||||
|
||||
if (!CheckDiskSpace() && !CheckDiskSpace(0, true))
|
||||
if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ false)) {
|
||||
InitError(strprintf(_("Error: Disk space is low for %s"), GetDataDir()));
|
||||
return false;
|
||||
}
|
||||
if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ true)) {
|
||||
InitError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
|
||||
// No locking, as this happens before any background thread is started.
|
||||
|
@ -326,15 +326,13 @@ bool IsLocal(const CService& addr)
|
||||
/** check whether a given network is one we can probably connect to */
|
||||
bool IsReachable(enum Network net)
|
||||
{
|
||||
LOCK(cs_mapLocalHost);
|
||||
return !vfLimited[net];
|
||||
return !IsLimited(net);
|
||||
}
|
||||
|
||||
/** check whether a given address is in a network we can probably connect to */
|
||||
bool IsReachable(const CNetAddr& addr)
|
||||
{
|
||||
enum Network net = addr.GetNetwork();
|
||||
return IsReachable(net);
|
||||
return IsReachable(addr.GetNetwork());
|
||||
}
|
||||
|
||||
|
||||
|
@ -81,6 +81,11 @@ public:
|
||||
#endif // ENABLE_WALLET
|
||||
bool enableWallet;
|
||||
|
||||
/** Get the tray icon status.
|
||||
Some systems have not "system tray" or "notification area" available.
|
||||
*/
|
||||
bool hasTrayIcon() const { return trayIcon; }
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e) override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
@ -497,14 +497,13 @@ void BitcoinApplication::initializeResult(bool success)
|
||||
}
|
||||
#endif
|
||||
|
||||
// If -min option passed, start window minimized.
|
||||
if(gArgs.GetBoolArg("-min", false))
|
||||
{
|
||||
window->showMinimized();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If -min option passed, start window minimized (iconified) or minimized to tray
|
||||
if (!gArgs.GetBoolArg("-min", false)) {
|
||||
window->show();
|
||||
} else if (clientModel->getOptionsModel()->getMinimizeToTray() && window->hasTrayIcon()) {
|
||||
// do nothing as the window is managed by the tray icon
|
||||
} else {
|
||||
window->showMinimized();
|
||||
}
|
||||
Q_EMIT splashFinished(window);
|
||||
|
||||
|
@ -945,7 +945,7 @@ https://www.transifex.com/projects/p/dash/</string>
|
||||
<item>
|
||||
<widget class="QLabel" name="overriddenByCommandLineInfoLabel">
|
||||
<property name="text">
|
||||
<string>Active command-line options that override above options:</string>
|
||||
<string>Options set in this dialog are overridden by the command line or in the configuration file:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
|
@ -39,7 +39,7 @@ Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon
|
||||
mode(None),
|
||||
trayIcon(_trayIcon)
|
||||
#ifdef USE_DBUS
|
||||
,interface(0)
|
||||
,interface(nullptr)
|
||||
#endif
|
||||
{
|
||||
if(_trayIcon && _trayIcon->supportsMessages())
|
||||
@ -154,14 +154,14 @@ QVariant FreedesktopImage::toVariant(const QImage &img)
|
||||
|
||||
void Notificator::notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
|
||||
{
|
||||
Q_UNUSED(cls);
|
||||
// Arguments for DBus call:
|
||||
// https://developer.gnome.org/notification-spec/
|
||||
// Arguments for DBus "Notify" call:
|
||||
QList<QVariant> args;
|
||||
|
||||
// Program Name:
|
||||
args.append(programName);
|
||||
|
||||
// Unique ID of this notification type:
|
||||
// Replaces ID; A value of 0 means that this notification won't replace any existing notifications:
|
||||
args.append(0U);
|
||||
|
||||
// Application Icon, empty string
|
||||
@ -209,9 +209,8 @@ void Notificator::notifyDBus(Class cls, const QString &title, const QString &tex
|
||||
}
|
||||
#endif
|
||||
|
||||
void Notificator::notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
|
||||
void Notificator::notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout)
|
||||
{
|
||||
Q_UNUSED(icon);
|
||||
QSystemTrayIcon::MessageIcon sicon = QSystemTrayIcon::NoIcon;
|
||||
switch(cls) // Set icon based on class
|
||||
{
|
||||
@ -222,13 +221,12 @@ void Notificator::notifySystray(Class cls, const QString &title, const QString &
|
||||
trayIcon->showMessage(title, text, sicon, millisTimeout);
|
||||
}
|
||||
|
||||
// Based on Qt's tray icon implementation
|
||||
#ifdef Q_OS_MAC
|
||||
void Notificator::notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon) {
|
||||
void Notificator::notifyMacUserNotificationCenter(const QString &title, const QString &text)
|
||||
{
|
||||
// icon is not supported by the user notification center yet. OSX will use the app icon.
|
||||
MacNotificationHandler::instance()->showNotification(title, text);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
|
||||
@ -241,11 +239,11 @@ void Notificator::notify(Class cls, const QString &title, const QString &text, c
|
||||
break;
|
||||
#endif
|
||||
case QSystemTray:
|
||||
notifySystray(cls, title, text, icon, millisTimeout);
|
||||
notifySystray(cls, title, text, millisTimeout);
|
||||
break;
|
||||
#ifdef Q_OS_MAC
|
||||
case UserNotificationCenter:
|
||||
notifyMacUserNotificationCenter(cls, title, text, icon);
|
||||
notifyMacUserNotificationCenter(title, text);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -57,7 +57,7 @@ private:
|
||||
enum Mode {
|
||||
None, /**< Ignore informational notifications, and show a modal pop-up dialog for Critical notifications. */
|
||||
Freedesktop, /**< Use DBus org.freedesktop.Notifications */
|
||||
QSystemTray, /**< Use QSystemTray::showMessage */
|
||||
QSystemTray, /**< Use QSystemTrayIcon::showMessage() */
|
||||
UserNotificationCenter /**< Use the 10.8+ User Notification Center (Mac only) */
|
||||
};
|
||||
QString programName;
|
||||
@ -68,9 +68,9 @@ private:
|
||||
|
||||
void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
|
||||
#endif
|
||||
void notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout);
|
||||
void notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout);
|
||||
#ifdef Q_OS_MAC
|
||||
void notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon);
|
||||
void notifyMacUserNotificationCenter(const QString &title, const QString &text);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -400,13 +400,12 @@ void RPCExecutor::request(const QString &command, const QString &walletID)
|
||||
std::string executableCommand = command.toStdString() + "\n";
|
||||
|
||||
// Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply.
|
||||
if(executableCommand == "help-console\n")
|
||||
{
|
||||
if(executableCommand == "help-console\n") {
|
||||
Q_EMIT reply(RPCConsole::CMD_REPLY, QString(("\n"
|
||||
"This console accepts RPC commands using the standard syntax.\n"
|
||||
" example: getblockhash 0\n\n"
|
||||
|
||||
"This console can also accept RPC commands using parenthesized syntax.\n"
|
||||
"This console can also accept RPC commands using the parenthesized syntax.\n"
|
||||
" example: getblockhash(0)\n\n"
|
||||
|
||||
"Commands may be nested when specified with the parenthesized syntax.\n"
|
||||
@ -416,11 +415,11 @@ void RPCExecutor::request(const QString &command, const QString &walletID)
|
||||
" example: getblockhash 0\n"
|
||||
" getblockhash,0\n\n"
|
||||
|
||||
"Named results can be queried with a non-quoted key string in brackets.\n"
|
||||
" example: getblock(getblockhash(0) true)[tx]\n\n"
|
||||
"Named results can be queried with a non-quoted key string in brackets using the parenthesized syntax.\n"
|
||||
" example: getblock(getblockhash(0) 1)[tx]\n\n"
|
||||
|
||||
"Results without keys can be queried using an integer in brackets.\n"
|
||||
" example: getblock(getblockhash(0),true)[tx][0]\n\n")));
|
||||
"Results without keys can be queried with an integer in brackets using the parenthesized syntax.\n"
|
||||
" example: getblock(getblockhash(0),1)[tx][0]\n\n")));
|
||||
return;
|
||||
}
|
||||
std::string wallet_id = walletID.toStdString();
|
||||
|
47
src/rest.cpp
47
src/rest.cpp
@ -573,6 +573,52 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
|
||||
}
|
||||
}
|
||||
|
||||
static bool rest_blockhash_by_height(HTTPRequest* req,
|
||||
const std::string& str_uri_part)
|
||||
{
|
||||
if (!CheckWarmup(req)) return false;
|
||||
std::string height_str;
|
||||
const RetFormat rf = ParseDataFormat(height_str, str_uri_part);
|
||||
|
||||
int32_t blockheight;
|
||||
if (!ParseInt32(height_str, &blockheight) || blockheight < 0) {
|
||||
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid height: " + SanitizeString(height_str));
|
||||
}
|
||||
|
||||
CBlockIndex* pblockindex = nullptr;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (blockheight > chainActive.Height()) {
|
||||
return RESTERR(req, HTTP_NOT_FOUND, "Block height out of range");
|
||||
}
|
||||
pblockindex = chainActive[blockheight];
|
||||
}
|
||||
switch (rf) {
|
||||
case RetFormat::BINARY: {
|
||||
CDataStream ss_blockhash(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss_blockhash << pblockindex->GetBlockHash();
|
||||
req->WriteHeader("Content-Type", "application/octet-stream");
|
||||
req->WriteReply(HTTP_OK, ss_blockhash.str());
|
||||
return true;
|
||||
}
|
||||
case RetFormat::HEX: {
|
||||
req->WriteHeader("Content-Type", "text/plain");
|
||||
req->WriteReply(HTTP_OK, pblockindex->GetBlockHash().GetHex() + "\n");
|
||||
return true;
|
||||
}
|
||||
case RetFormat::JSON: {
|
||||
req->WriteHeader("Content-Type", "application/json");
|
||||
UniValue resp = UniValue(UniValue::VOBJ);
|
||||
resp.pushKV("blockhash", pblockindex->GetBlockHash().GetHex());
|
||||
req->WriteReply(HTTP_OK, resp.write() + "\n");
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char* prefix;
|
||||
bool (*handler)(HTTPRequest* req, const std::string& strReq);
|
||||
@ -585,6 +631,7 @@ static const struct {
|
||||
{"/rest/mempool/contents", rest_mempool_contents},
|
||||
{"/rest/headers/", rest_headers},
|
||||
{"/rest/getutxos", rest_getutxos},
|
||||
{"/rest/blockhashbyheight/", rest_blockhash_by_height},
|
||||
};
|
||||
|
||||
bool StartREST()
|
||||
|
@ -41,7 +41,11 @@ struct secure_allocator : public std::allocator<T> {
|
||||
|
||||
T* allocate(std::size_t n, const void* hint = 0)
|
||||
{
|
||||
return static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
|
||||
T* allocation = static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
|
||||
if (!allocation) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return allocation;
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
|
@ -252,6 +252,9 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess)
|
||||
void *addr;
|
||||
len = align_up(len, page_size);
|
||||
addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
if (addr == MAP_FAILED) {
|
||||
return nullptr;
|
||||
}
|
||||
if (addr) {
|
||||
*lockingSuccess = mlock(addr, len) == 0;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
virtual ~LockedPageAllocator() {}
|
||||
/** Allocate and lock memory pages.
|
||||
* If len is not a multiple of the system page size, it is rounded up.
|
||||
* Returns 0 in case of allocation failure.
|
||||
* Returns nullptr in case of allocation failure.
|
||||
*
|
||||
* If locking the memory pages could not be accomplished it will still
|
||||
* return the memory, however the lockingSuccess flag will be false.
|
||||
|
@ -81,7 +81,11 @@ struct LockData {
|
||||
LockOrders lockorders;
|
||||
InvLockOrders invlockorders;
|
||||
std::mutex dd_mutex;
|
||||
} static lockdata;
|
||||
};
|
||||
LockData& GetLockData() {
|
||||
static LockData lockdata;
|
||||
return lockdata;
|
||||
}
|
||||
|
||||
static thread_local LockStack g_lockstack;
|
||||
|
||||
@ -122,6 +126,7 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
|
||||
|
||||
static void push_lock(void* c, const CLockLocation& locklocation)
|
||||
{
|
||||
LockData& lockdata = GetLockData();
|
||||
std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
|
||||
|
||||
g_lockstack.push_back(std::make_pair(c, locklocation));
|
||||
@ -189,6 +194,7 @@ void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLi
|
||||
|
||||
void DeleteLock(void* cs)
|
||||
{
|
||||
LockData& lockdata = GetLockData();
|
||||
if (!lockdata.available) {
|
||||
// We're already shutting down.
|
||||
return;
|
||||
|
@ -626,4 +626,93 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
|
||||
BOOST_CHECK(1);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
|
||||
{
|
||||
SetLimited(NET_IPV4, true);
|
||||
SetLimited(NET_IPV6, true);
|
||||
SetLimited(NET_ONION, true);
|
||||
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_IPV4), true);
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_IPV6), true);
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_ONION), true);
|
||||
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), false);
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), false);
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_ONION), false);
|
||||
|
||||
|
||||
SetLimited(NET_IPV4, false);
|
||||
SetLimited(NET_IPV6, false);
|
||||
SetLimited(NET_ONION, false);
|
||||
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_IPV4), false);
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_IPV6), false);
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_ONION), false);
|
||||
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_UNROUTABLE), false);
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_INTERNAL), false);
|
||||
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
|
||||
|
||||
SetLimited(NET_UNROUTABLE, true);
|
||||
SetLimited(NET_INTERNAL, true);
|
||||
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_UNROUTABLE), false); // Ignored for both networks
|
||||
BOOST_CHECK_EQUAL(IsLimited(NET_INTERNAL), false);
|
||||
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
|
||||
BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
|
||||
}
|
||||
|
||||
CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
|
||||
{
|
||||
unsigned char ip[] = {p1, p2, p3, p4};
|
||||
|
||||
struct sockaddr_in sa;
|
||||
memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block
|
||||
memcpy(&(sa.sin_addr), &ip, sizeof(ip));
|
||||
return CNetAddr(sa.sin_addr);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
|
||||
{
|
||||
CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
|
||||
|
||||
SetLimited(NET_IPV4, false);
|
||||
BOOST_CHECK_EQUAL(IsLimited(addr), false);
|
||||
BOOST_CHECK_EQUAL(IsReachable(addr), true);
|
||||
|
||||
SetLimited(NET_IPV4, true);
|
||||
BOOST_CHECK_EQUAL(IsLimited(addr), true);
|
||||
BOOST_CHECK_EQUAL(IsReachable(addr), false);
|
||||
|
||||
SetLimited(NET_IPV4, false); // have to reset this, because this is stateful.
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
|
||||
{
|
||||
CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
|
||||
|
||||
SetLimited(NET_IPV4, false);
|
||||
|
||||
BOOST_CHECK_EQUAL(IsLocal(addr), false);
|
||||
BOOST_CHECK_EQUAL(AddLocal(addr, 1000), true);
|
||||
BOOST_CHECK_EQUAL(IsLocal(addr), true);
|
||||
|
||||
RemoveLocal(addr);
|
||||
BOOST_CHECK_EQUAL(IsLocal(addr), false);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -213,14 +213,22 @@ BOOST_AUTO_TEST_CASE(is)
|
||||
BOOST_CHECK(p2sh.IsPayToScriptHash());
|
||||
|
||||
// Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes:
|
||||
static const unsigned char direct[] = { OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
|
||||
BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToScriptHash());
|
||||
static const unsigned char pushdata1[] = { OP_HASH160, OP_PUSHDATA1, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
|
||||
BOOST_CHECK(!CScript(pushdata1, pushdata1+sizeof(pushdata1)).IsPayToScriptHash());
|
||||
static const unsigned char pushdata2[] = { OP_HASH160, OP_PUSHDATA2, 20,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
|
||||
BOOST_CHECK(!CScript(pushdata2, pushdata2+sizeof(pushdata2)).IsPayToScriptHash());
|
||||
static const unsigned char pushdata4[] = { OP_HASH160, OP_PUSHDATA4, 20,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
|
||||
BOOST_CHECK(!CScript(pushdata4, pushdata4+sizeof(pushdata4)).IsPayToScriptHash());
|
||||
std::vector<unsigned char> direct = {OP_HASH160, 20};
|
||||
direct.insert(direct.end(), 20, 0);
|
||||
direct.push_back(OP_EQUAL);
|
||||
BOOST_CHECK(CScript(direct.begin(), direct.end()).IsPayToScriptHash());
|
||||
std::vector<unsigned char> pushdata1 = {OP_HASH160, OP_PUSHDATA1, 20};
|
||||
pushdata1.insert(pushdata1.end(), 20, 0);
|
||||
pushdata1.push_back(OP_EQUAL);
|
||||
BOOST_CHECK(!CScript(pushdata1.begin(), pushdata1.end()).IsPayToScriptHash());
|
||||
std::vector<unsigned char> pushdata2 = {OP_HASH160, 20, 0};
|
||||
pushdata2.insert(pushdata2.end(), 20, 0);
|
||||
pushdata2.push_back(OP_EQUAL);
|
||||
BOOST_CHECK(!CScript(pushdata2.begin(), pushdata2.end()).IsPayToScriptHash());
|
||||
std::vector<unsigned char> pushdata4 = {OP_HASH160, 20, 0, 0, 0};
|
||||
pushdata4.insert(pushdata4.end(), 20, 0);
|
||||
pushdata4.push_back(OP_EQUAL);
|
||||
BOOST_CHECK(!CScript(pushdata4.begin(), pushdata4.end()).IsPayToScriptHash());
|
||||
|
||||
CScript not_p2sh;
|
||||
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
|
||||
|
@ -763,18 +763,17 @@ fs::path GetDefaultDataDir()
|
||||
#endif
|
||||
}
|
||||
|
||||
static fs::path g_blocks_path_cached;
|
||||
static fs::path g_blocks_path_cache_net_specific;
|
||||
static fs::path pathCached;
|
||||
static fs::path pathCachedNetSpecific;
|
||||
static CCriticalSection csPathCached;
|
||||
|
||||
const fs::path &GetBlocksDir(bool fNetSpecific)
|
||||
const fs::path &GetBlocksDir()
|
||||
{
|
||||
|
||||
LOCK(csPathCached);
|
||||
|
||||
fs::path &path = fNetSpecific ? g_blocks_path_cache_net_specific : g_blocks_path_cached;
|
||||
fs::path &path = g_blocks_path_cache_net_specific;
|
||||
|
||||
// This can be called during exceptions by LogPrintf(), so we cache the
|
||||
// value so we don't have to do memory allocations after that.
|
||||
@ -790,9 +789,8 @@ const fs::path &GetBlocksDir(bool fNetSpecific)
|
||||
} else {
|
||||
path = GetDataDir(false);
|
||||
}
|
||||
if (fNetSpecific)
|
||||
path /= BaseParams().DataDir();
|
||||
|
||||
path /= BaseParams().DataDir();
|
||||
path /= "blocks";
|
||||
fs::create_directories(path);
|
||||
return path;
|
||||
@ -844,7 +842,6 @@ void ClearDatadirCache()
|
||||
|
||||
pathCached = fs::path();
|
||||
pathCachedNetSpecific = fs::path();
|
||||
g_blocks_path_cached = fs::path();
|
||||
g_blocks_path_cache_net_specific = fs::path();
|
||||
}
|
||||
|
||||
@ -1281,7 +1278,7 @@ fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific)
|
||||
int ScheduleBatchPriority(void)
|
||||
{
|
||||
#ifdef SCHED_BATCH
|
||||
const static sched_param param{0};
|
||||
const static sched_param param{};
|
||||
if (int ret = pthread_setschedparam(pthread_self(), SCHED_BATCH, ¶m)) {
|
||||
LogPrintf("Failed to pthread_setschedparam: %s\n", strerror(errno));
|
||||
return ret;
|
||||
|
@ -108,7 +108,8 @@ void ReleaseDirectoryLocks();
|
||||
|
||||
bool TryCreateDirectories(const fs::path& p);
|
||||
fs::path GetDefaultDataDir();
|
||||
const fs::path &GetBlocksDir(bool fNetSpecific = true);
|
||||
// The blocks directory is always net specific.
|
||||
const fs::path &GetBlocksDir();
|
||||
const fs::path &GetDataDir(bool fNetSpecific = true);
|
||||
fs::path GetBackupsDir();
|
||||
void ClearDatadirCache();
|
||||
|
@ -4508,7 +4508,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
||||
LogPrintf("[0%%]..."); /* Continued */
|
||||
for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
|
||||
boost::this_thread::interruption_point();
|
||||
int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
|
||||
const int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
|
||||
if (reportDone < percentageDone/10) {
|
||||
// report every 10% step
|
||||
LogPrintf("[%d%%]...", percentageDone); /* Continued */
|
||||
@ -4566,7 +4566,13 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
||||
if (nCheckLevel >= 4) {
|
||||
while (pindex != chainActive.Tip()) {
|
||||
boost::this_thread::interruption_point();
|
||||
uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))), false);
|
||||
const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)));
|
||||
if (reportDone < percentageDone/10) {
|
||||
// report every 10% step
|
||||
LogPrintf("[%d%%]...", percentageDone); /* Continued */
|
||||
reportDone = percentageDone/10;
|
||||
}
|
||||
uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, false);
|
||||
pindex = chainActive.Next(pindex);
|
||||
CBlock block;
|
||||
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
|
||||
|
@ -17,7 +17,8 @@ request is opened. Both sets of tests can also be run locally.
|
||||
|
||||
# Running tests locally
|
||||
|
||||
Build for your system first. Be sure to enable wallet, utils and daemon when you configure. Tests will not run otherwise.
|
||||
Before tests can be run locally, Dash Core must be built. See the [building instructions](/doc#building) for help.
|
||||
|
||||
|
||||
### Functional tests
|
||||
|
||||
|
@ -20,9 +20,13 @@ don't have test cases for.
|
||||
- Where possible, try to adhere to [PEP-8 guidelines](https://www.python.org/dev/peps/pep-0008/)
|
||||
- Use a python linter like flake8 before submitting PRs to catch common style
|
||||
nits (eg trailing whitespace, unused imports, etc)
|
||||
- The oldest supported Python version is specified in [doc/dependencies.md](/doc/dependencies.md).
|
||||
Consider using [pyenv](https://github.com/pyenv/pyenv), which checks [.python-version](/.python-version),
|
||||
to prevent accidentally introducing modern syntax from an unsupported Python version.
|
||||
The Travis linter also checks this, but [possibly not in all cases](https://github.com/bitcoin/bitcoin/pull/14884#discussion_r239585126).
|
||||
- See [the python lint script](/test/lint/lint-python.sh) that checks for violations that
|
||||
could lead to bugs and issues in the test code.
|
||||
- Avoid wildcard imports where possible
|
||||
- Avoid wildcard imports
|
||||
- Use a module-level docstring to describe what the test is testing, and how it
|
||||
is testing it.
|
||||
- When subclassing the BitcoinTestFramwork, place overrides for the
|
||||
|
@ -13,7 +13,7 @@ is testing and *how* it's being tested
|
||||
# libraries then local imports).
|
||||
from collections import defaultdict
|
||||
|
||||
# Avoid wildcard * imports if possible
|
||||
# Avoid wildcard * imports
|
||||
from test_framework.blocktools import (create_block, create_coinbase)
|
||||
from test_framework.messages import CInv
|
||||
from test_framework.mininode import (
|
||||
|
@ -18,6 +18,8 @@ class BlocksdirTest(BitcoinTestFramework):
|
||||
|
||||
def run_test(self):
|
||||
self.stop_node(0)
|
||||
assert os.path.isdir(os.path.join(self.nodes[0].datadir, "regtest", "blocks"))
|
||||
assert not os.path.isdir(os.path.join(self.nodes[0].datadir, "blocks"))
|
||||
shutil.rmtree(self.nodes[0].datadir)
|
||||
initialize_datadir(self.options.tmpdir, 0, self.chain)
|
||||
self.log.info("Starting with non exiting blocksdir ...")
|
||||
|
@ -195,9 +195,19 @@ class RESTTest (BitcoinTestFramework):
|
||||
self.nodes[0].generate(1) # generate block to not affect upcoming tests
|
||||
self.sync_all()
|
||||
|
||||
self.log.info("Test the /block and /headers URIs")
|
||||
self.log.info("Test the /block, /blockhashbyheight and /headers URIs")
|
||||
bb_hash = self.nodes[0].getbestblockhash()
|
||||
|
||||
# Check result if block does not exists
|
||||
assert_equal(self.test_rest_request('/headers/1/0000000000000000000000000000000000000000000000000000000000000000'), [])
|
||||
self.test_rest_request('/block/0000000000000000000000000000000000000000000000000000000000000000', status=404, ret_type=RetType.OBJ)
|
||||
|
||||
# Check result if block is not in the active chain
|
||||
self.nodes[0].invalidateblock(bb_hash)
|
||||
assert_equal(self.test_rest_request('/headers/1/{}'.format(bb_hash)), [])
|
||||
self.test_rest_request('/block/{}'.format(bb_hash))
|
||||
self.nodes[0].reconsiderblock(bb_hash)
|
||||
|
||||
# Check binary format
|
||||
response = self.test_rest_request("/block/{}".format(bb_hash), req_type=ReqType.BIN, ret_type=RetType.OBJ)
|
||||
assert_greater_than(int(response.getheader('content-length')), 80)
|
||||
@ -224,6 +234,23 @@ class RESTTest (BitcoinTestFramework):
|
||||
# Check json format
|
||||
block_json_obj = self.test_rest_request("/block/{}".format(bb_hash))
|
||||
assert_equal(block_json_obj['hash'], bb_hash)
|
||||
assert_equal(self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']))['blockhash'], bb_hash)
|
||||
|
||||
# Check hex/bin format
|
||||
resp_hex = self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']), req_type=ReqType.HEX, ret_type=RetType.OBJ)
|
||||
assert_equal(resp_hex.read().decode('utf-8').rstrip(), bb_hash)
|
||||
resp_bytes = self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']), req_type=ReqType.BIN, ret_type=RetType.BYTES)
|
||||
blockhash = binascii.hexlify(resp_bytes[::-1]).decode('utf-8')
|
||||
assert_equal(blockhash, bb_hash)
|
||||
|
||||
# Check invalid blockhashbyheight requests
|
||||
resp = self.test_rest_request("/blockhashbyheight/abc", ret_type=RetType.OBJ, status=400)
|
||||
assert_equal(resp.read().decode('utf-8').rstrip(), "Invalid height: abc")
|
||||
resp = self.test_rest_request("/blockhashbyheight/1000000", ret_type=RetType.OBJ, status=404)
|
||||
assert_equal(resp.read().decode('utf-8').rstrip(), "Block height out of range")
|
||||
resp = self.test_rest_request("/blockhashbyheight/-1", ret_type=RetType.OBJ, status=400)
|
||||
assert_equal(resp.read().decode('utf-8').rstrip(), "Invalid height: -1")
|
||||
self.test_rest_request("/blockhashbyheight/", ret_type=RetType.OBJ, status=400)
|
||||
|
||||
# Compare with json block header
|
||||
json_obj = self.test_rest_request("/headers/1/{}".format(bb_hash))
|
||||
|
@ -70,7 +70,7 @@ class RPCBindTest(BitcoinTestFramework):
|
||||
|
||||
self.log.info("Check for ipv6")
|
||||
have_ipv6 = test_ipv6_local()
|
||||
if not have_ipv6 and not self.options.run_ipv4:
|
||||
if not have_ipv6 and not (self.options.run_ipv4 or self.options.run_nonloopback):
|
||||
raise SkipTest("This test requires ipv6 support.")
|
||||
|
||||
self.log.info("Check for non-loopback interface")
|
||||
|
@ -22,26 +22,29 @@ if ! command -v shellcheck > /dev/null; then
|
||||
fi
|
||||
|
||||
# Disabled warnings:
|
||||
# SC1087: Use braces when expanding arrays, e.g. ${array[idx]} (or ${var}[.. to quiet).
|
||||
# SC1117: Backslash is literal in "\.". Prefer explicit escaping: "\\.".
|
||||
# SC2001: See if you can use ${variable//search/replace} instead.
|
||||
# SC2004: $/${} is unnecessary on arithmetic variables.
|
||||
# SC2005: Useless echo? Instead of 'echo $(cmd)', just use 'cmd'.
|
||||
# SC2006: Use $(..) instead of legacy `..`.
|
||||
# SC2016: Expressions don't expand in single quotes, use double quotes for that.
|
||||
# SC2028: echo won't expand escape sequences. Consider printf.
|
||||
# SC2046: Quote this to prevent word splitting.
|
||||
# SC2048: Use "$@" (with quotes) to prevent whitespace problems.
|
||||
# SC2066: Since you double quoted this, it will not word split, and the loop will only run once.
|
||||
# SC2086: Double quote to prevent globbing and word splitting.
|
||||
# SC2116: Useless echo? Instead of 'cmd $(echo foo)', just use 'cmd foo'.
|
||||
# SC2148: Tips depend on target shell and yours is unknown. Add a shebang.
|
||||
# SC2162: read without -r will mangle backslashes.
|
||||
# SC2166: Prefer [ p ] && [ q ] as [ p -a q ] is not well defined.
|
||||
# SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
|
||||
# SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
|
||||
# SC2206: Quote to prevent word splitting, or split robustly with mapfile or read -a.
|
||||
# SC2207: Prefer mapfile or read -a to split command output (or quote to avoid splitting).
|
||||
# SC2230: which is non-standard. Use builtin 'command -v' instead.
|
||||
shellcheck -e SC1087,SC1117,SC2001,SC2004,SC2005,SC2006,SC2016,SC2028,SC2046,SC2048,SC2066,SC2086,SC2116,SC2148,SC2162,SC2166,SC2181,SC2206,SC2207,SC2230 \
|
||||
disabled=(
|
||||
SC1087 # Use braces when expanding arrays, e.g. ${array[idx]} (or ${var}[.. to quiet).
|
||||
SC1117 # Backslash is literal in "\.". Prefer explicit escaping: "\\.".
|
||||
SC2001 # See if you can use ${variable//search/replace} instead.
|
||||
SC2004 # $/${} is unnecessary on arithmetic variables.
|
||||
SC2005 # Useless echo? Instead of 'echo $(cmd)', just use 'cmd'.
|
||||
SC2006 # Use $(..) instead of legacy `..`.
|
||||
SC2016 # Expressions don't expand in single quotes, use double quotes for that.
|
||||
SC2028 # echo won't expand escape sequences. Consider printf.
|
||||
SC2046 # Quote this to prevent word splitting.
|
||||
SC2048 # Use "$@" (with quotes) to prevent whitespace problems.
|
||||
SC2066 # Since you double quoted this, it will not word split, and the loop will only run once.
|
||||
SC2086 # Double quote to prevent globbing and word splitting.
|
||||
SC2116 # Useless echo? Instead of 'cmd $(echo foo)', just use 'cmd foo'.
|
||||
SC2148 # Tips depend on target shell and yours is unknown. Add a shebang.
|
||||
SC2162 # read without -r will mangle backslashes.
|
||||
SC2166 # Prefer [ p ] && [ q ] as [ p -a q ] is not well defined.
|
||||
SC2166 # Prefer [ p ] || [ q ] as [ p -o q ] is not well defined.
|
||||
SC2181 # Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
|
||||
SC2206 # Quote to prevent word splitting, or split robustly with mapfile or read -a.
|
||||
SC2207 # Prefer mapfile or read -a to split command output (or quote to avoid splitting).
|
||||
SC2230 # which is non-standard. Use builtin 'command -v' instead.
|
||||
SC2236 # Don't force -n instead of ! -z.
|
||||
)
|
||||
shellcheck -e "$(IFS=","; echo "${disabled[*]}")" \
|
||||
$(git ls-files -- "*.sh" | grep -vE 'src/(secp256k1|univalue)/')
|
||||
|
Loading…
Reference in New Issue
Block a user