diff --git a/contrib/rpm/README.md b/contrib/rpm/README.md
index e1fd0b317b..4ab2f35680 100644
--- a/contrib/rpm/README.md
+++ b/contrib/rpm/README.md
@@ -1,185 +1,185 @@
RPM Spec File Notes
-------------------
The RPM spec file provided here is for Bitcoin-Core 0.12.0 and builds on CentOS
7 with either the CentOS provided OpenSSL library or with LibreSSL as packaged
at [LibreLAMP.com](https://librelamp.com/). It should hopefully not be too
difficult to port the RPM spec file to most RPM based Linux distributions.
When porting the spec file to build for a particular distribution, there are
some important notes.
## Sources
It is considered good form for all sources to reference a URL where the source
can be downloaded.
Sources 0-9 should be reserved for source code tarballs. `Source0` should
reference the release tarball available from https://bitcoin.org/bin/ and
`Source1` should reference the BerkeleyDB source.
Sources 10-99 are for source files that are maintained in the
[Bitcoin git repository](https://github.com/bitcoin/bitcoin) but are not part of
the release tarball. Most of these will reside in the `contrib` sub-directory.
Sources 10-19 should be reserved for miscellaneous configuration files.
Currently only `Source10` is used, for the example `bitcoin.conf` file.
Sources 20-29 should be reserved for man pages. Currently only `Source20`
through `Source23` are used.
Sources 30-39 should be reserved for SELinux related files. Currently only
`Source30` through `Source32` are used. Until those files are in a tagged
release, the full URL specified in the RPM spec file will not work. You can get
them from the git repository where you retrieved this file.
Sources 100+ are for files that are not source tarballs and are not maintained
in the bitcoin git repository. At present only an SVG version of the Bitcoin
icon is used.
## Patches
In general, patches should be avoided. When a packager feels a patch is
necessary, the packager should bring the problem to the attention of the bitcoin
developers so that an official fix to the issue can make it into the next
release.
### Patch0 bitcoin-0.12.0-libressl.patch
This patch is only needed if building against LibreSSL. LibreSSL is not the
standard TLS library on most Linux distributions. The patch will likely not be
needed when 0.12.1 is released, a proper fix is already in the Bitcoin git
master branch.
## BuildRequires
The packages specified in the `BuildRequires` are specified according to the
package naming convention currently used in CentOS 7 and EPEL for CentOS 7. You
may need to change some of the package names for other distributions. This is
most likely to be the case with the Qt packages.
## BerkeleyDB
The `build-unix.md` file recommends building against BerkeleyDB 4.8.30. Even if
that is the version your Linux distribution ships with, it probably is a good
idea to build Bitcoin Core against a static version of that library compiled
according to the instructions in the `build-unix.md` file so that any changes
the distribution may make in the future will not result in a problem for users.
The problem that can exist, clients built against different versions of
BerkeleyDB may not be able read each other's `wallet.dat` file which can make it
difficult for a user to recover from backup in the event of a system failure.
## Graphical User Interface and Qt Version
The RPM spec file will by default build the GUI client linked against the Qt5
libraries. If you wish instead to link against the Qt4 libraries you need to
pass the switch `-D '_use_qt4 1'` at build time to the `rpmbuild` or `mock`
command used to build the packages.
If you would prefer not to build the GUI at all, you can pass the switch
`-D '_no_gui 1'` to the `rpmbuild` or `mock` build command.
## Desktop and KDE Files
The desktop and KDE meta files are created in the spec file itself with the
`cat` command. This is done to allow easy distribution specific changes without
needing to use any patches. A specific time stamp is given to the files so that
it does not they do not appear to have been updated every time the package is
built. If you do make changes to them, you probably should update time stamp
assigned to them in the `touch` command that specifies the time stamp.
## SVG, PNG, and XPM Icons
The `bitcoin.svg` file is from the source listed as `Source100`. It is used as
the source for the PNG and XPM files. The generated PNG and XPM files are given
the same time stamp as the source SVG file as a means of indicating they are
derived from it.
## Systemd
This spec file assumes the target distribution uses systemd. That really only
matters for the `bitcoin-server` package. At this point, most RPM based
distributions that still receive vendor updates do in fact use systemd.
The files to control the service are created in the RPM spec file itself using
the `cat` command. This is done to make it easy to modify for other
distributions that may implement things differently without needing to patch
source. A specific time stamp is given to the files so that they do not appear
to have been updated every time the package is built. If you do make changes to
them, you probably should update the time stamp assigned to them in the `touch`
command that specifies the time stamp.
## SELinux
The `bitcoin-server` package should have SELinux support. How to properly do
that *may* vary by distribution and version of distribution.
The SELinux stuff in this RPM spec file *should* be correct for CentOS, RHEL,
and Fedora but it would be a good idea to review it before building the package
on other distributions.
## Tests
The `%check` section takes a very long time to run. If your build system has a
time limit for package build, you may need to make an exception for this
package. On CentOS 7 the `%check` section completes successfully with both
OpenSSL and LibreSSL, a failure really does mean something is wrong.
## LibreSSL Build Notes
To build against LibreSSL you will need to pass the switch
`-D '_use_libressl 1'` to the `rpmbuild` or `mock` command or the spec file will
want the OpenSSL development files.
### LibreSSL and Boost
LibreSSL (and some newer builds of OpenSSL) do not have support for SSLv3. This
can cause issues with the Boost package if the Boost package has not been
patched accordingly. On those distributions, you will either need to build
Bitcoin-Core against OpenSSL or use a patched version of Boost in the build
system.
As SSLv3 is no longer safe, distributions that have not patched Boost to work
with TLS libraries that do not support SSLv3 should have bug reports filed
against the Boost package. This bug report has already been filed for RHEL 7 but
it may need to be filed for other distributions.
A patch for Boost: https://github.com/boostorg/asio/pull/23/files
## ZeroMQ
At this time, this RPM spec file does not support the ZeroMQ build options. A
suitable version of ZeroMQ is not available for the platform this spec file was
developed on (CentOS 7).
## Legacy Credit
This RPM spec file is largely based upon the work of Michael Hampton at
[Ringing Liberty](https://www.ringingliberty.com/bitcoin/). He has been
packaging Bitcoin for Fedora at least since 2012.
Most of the differences between his packaging and this package are stylistic in
nature. The major differences:
1. He builds from a github tagged release rather than a release tarball. This
should not result in different source code.
2. He does not build BerkeleyDB but instead uses the BerkeleyDB provided by the
Linux distribution. For the distributions he packages for, they currently all
use the same version of BerkeleyDB so that difference is *probably* just
academic.
3. As of his 10.11.2 package he did not allow for building against LibreSSL,
specifying a build without the Qt GUI, or specifying which version of the Qt
libraries to use.
4. I renamed the `bitcoin` package that contains the Qt GUI to `bitcoin-core` as
that appears to be how the general population refers to it, in contrast to
`bitcoin-xt` or `bitcoin-classic`. I wanted to make sure the general population
knows what they are getting when installing the GUI package.
As far as minor differences, I generally prefer to assign the file permissions
in the `%files` portion of an RPM spec file rather than specifying the
-permissions of a file during `%install` and other minor things like that that
+permissions of a file during `%install` and other minor things like that
are largely just cosmetic.
diff --git a/contrib/rpm/bitcoin.if b/contrib/rpm/bitcoin.if
index 2b096c24dc..b206866cc5 100644
--- a/contrib/rpm/bitcoin.if
+++ b/contrib/rpm/bitcoin.if
@@ -1,157 +1,157 @@
## policy for bitcoin
########################################
##
## Transition to bitcoin.
##
##
##
## Domain allowed to transition.
##
##
#
interface(`bitcoin_domtrans',`
gen_require(`
type bitcoin_t, bitcoin_exec_t;
')
corecmd_search_bin($1)
domtrans_pattern($1, bitcoin_exec_t, bitcoin_t)
')
########################################
##
## Execute bitcoin server in the bitcoin domain.
##
##
##
## Domain allowed access.
##
##
#
interface(`bitcoin_initrc_domtrans',`
gen_require(`
type bitcoin_initrc_exec_t;
')
init_labeled_script_domtrans($1, bitcoin_initrc_exec_t)
')
########################################
##
## Search bitcoin lib directories.
##
##
##
## Domain allowed access.
##
##
#
interface(`bitcoin_search_lib',`
gen_require(`
type bitcoin_var_lib_t;
')
allow $1 bitcoin_var_lib_t:dir search_dir_perms;
files_search_var_lib($1)
')
########################################
##
## Read bitcoin lib files.
##
##
##
## Domain allowed access.
##
##
#
interface(`bitcoin_read_lib_files',`
gen_require(`
type bitcoin_var_lib_t;
')
files_search_var_lib($1)
read_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t)
')
########################################
##
## Manage bitcoin lib files.
##
##
##
## Domain allowed access.
##
##
#
interface(`bitcoin_manage_lib_files',`
gen_require(`
type bitcoin_var_lib_t;
')
files_search_var_lib($1)
manage_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t)
')
########################################
##
## Manage bitcoin lib directories.
##
##
##
## Domain allowed access.
##
##
#
interface(`bitcoin_manage_lib_dirs',`
gen_require(`
type bitcoin_var_lib_t;
')
files_search_var_lib($1)
manage_dirs_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t)
')
########################################
##
## All of the rules required to administrate
-## an bitcoin environment
+## a bitcoin environment
##
##
##
## Domain allowed access.
##
##
##
##
## Role allowed access.
##
##
##
#
interface(`bitcoin_admin',`
gen_require(`
type bitcoin_t;
type bitcoin_initrc_exec_t;
type bitcoin_var_lib_t;
')
allow $1 bitcoin_t:process { ptrace signal_perms };
ps_process_pattern($1, bitcoin_t)
bitcoin_initrc_domtrans($1)
domain_system_change_exemption($1)
role_transition $2 bitcoin_initrc_exec_t system_r;
allow $2 system_r;
files_search_var_lib($1)
admin_pattern($1, bitcoin_var_lib_t)
')
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index f83e54cf9b..83eee83a00 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -1,711 +1,711 @@
Developer Notes
===============
Various coding styles have been used during the history of the codebase,
and the result is not very consistent. However, we're now trying to converge to
a single style, so please use it in new code. Old code will be converted
gradually and you are encouraged to use the provided
[clang-format-diff script](/contrib/devtools/README.md#clang-format-diffpy)
to clean up the patch automatically before submitting a pull request.
- Basic rules specified in [src/.clang-format](/src/.clang-format).
- Braces on new lines for namespaces, classes, functions, methods.
- Braces on the same line for everything else.
- 4 space indentation (no tabs) for every block except namespaces.
- No indentation for `public`/`protected`/`private` or for `namespace`.
- No extra spaces inside parenthesis; don't do ( this )
- No space after function names; one space after `if`, `for` and `while`.
- Always add braces for block statements (e.g. `if`, `for`, `while`).
- `++i` is preferred over `i++`.
- `static_assert` is preferred over `assert` where possible.
Generally; compile-time checking is preferred over run-time checking.
- Use CamelCase for functions/methods, and lowerCamelCase for variables.
- GLOBAL_CONSTANTS should use UPPER_SNAKE_CASE.
- namespaces should use lower_snake_case.
- Function names should generally start with an English command-form verb
(e.g. `ValidateTransaction`, `AddTransactionToMempool`, `ConnectBlock`)
- Variable names should generally be nouns or past/future tense verbs.
(e.g. `canDoThing`, `signatureOperations`, `didThing`)
- Avoid using globals, remove existing globals whenever possible.
- Class member variable names should be prepended with `m_`
- DO choose easily readable identifier names.
- DO favor readability over brevity.
- DO NOT use Hungarian notation.
- DO NOT use abbreviations or contractions within identifiers.
- WRONG: mempool
- RIGHT: MemoryPool
- WRONG: ChangeDir
- RIGHT: ChangeDirectory
- DO NOT use obscure acronyms, DO uppercase any acronyms.
- FINALLY, do not migrate existing code unless refactoring. It makes
forwarding-porting from Bitcoin Core more difficult.
The naming convention roughly mirrors [Microsoft Naming Conventions](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/general-naming-conventions)
C++ Coding Standards should strive to follow the [LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html)
Code style example:
```c++
// namespaces should be lower_snake_case
namespace foo_bar_bob {
/**
* Class is used for doing classy things. All classes should
* have a doxygen comment describing their PURPOSE. That is to say,
* why they exist. Functional details can be determined from the code.
* @see PerformTask()
*/
class Class {
private:
//! memberVariable's name should be lowerCamelCase, and be a noun.
int m_memberVariable;
public:
/**
* The documentation before a function or class method should follow Doxygen
* spec. The name of the function should start with an english verb which
* indicates the intended purpose of this code.
*
* The function name should be should be CamelCase.
*
* @param[in] s A description
* @param[in] n Another argument description
* @pre Precondition for function...
*/
bool PerformTask(const std::string& s, int n) {
// Use lowerChamelCase for local variables.
bool didMore = false;
// Comment summarizing the intended purpose of this section of code
for (int i = 0; i < n; ++i) {
if (!DidSomethingFail()) {
return false;
}
...
if (IsSomethingElse()) {
DoMore();
didMore = true;
} else {
DoLess();
}
}
return didMore;
}
}
}
```
Doxygen comments
-----------------
To facilitate the generation of documentation, use doxygen-compatible comment blocks for functions, methods and fields.
For example, to describe a function use:
```c++
/**
* ... text ...
* @param[in] arg1 A description
* @param[in] arg2 Another argument description
* @pre Precondition for function...
*/
bool function(int arg1, const char *arg2)
```
A complete list of `@xxx` commands can be found at http://www.stack.nl/~dimitri/doxygen/manual/commands.html.
As Doxygen recognizes the comments by the delimiters (`/**` and `*/` in this case), you don't
*need* to provide any commands for a comment to be valid; just a description text is fine.
To describe a class use the same construct above the class definition:
```c++
/**
* Alerts are for notifying old versions if they become too obsolete and
* need to upgrade. The message is displayed in the status bar.
* @see GetWarnings()
*/
class CAlert
{
```
To describe a member or variable use:
```c++
int var; //!< Detailed description after the member
```
or
```cpp
//! Description before the member
int var;
```
Also OK:
```c++
///
/// ... text ...
///
bool function2(int arg1, const char *arg2)
```
Not OK (used plenty in the current source, but not picked up):
```c++
//
// ... text ...
//
```
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.
To build doxygen locally to test changes to the Doxyfile or visualize your comments before landing changes:
```
# at the project root, call:
doxygen doc/Doxyfile
# output goes to doc/doxygen/html/
```
Development tips and tricks
---------------------------
**compiling for debugging**
Run configure with the --enable-debug option, then make. Or run configure with
CXXFLAGS="-g -ggdb -O0" or whatever debug flags you need.
**debug.log**
If the code is behaving strangely, take a look in the debug.log file in the data directory;
error and debugging messages are written there.
The -debug=... command-line option controls debugging; running with just -debug or -debug=1 will turn
on all categories (and give you a very large debug.log file).
The Qt code routes qDebug() output to debug.log under category "qt": run with -debug=qt
to see it.
**writing tests**
For details on unit tests, see `unit-tests.md`
For details on functional tests, see `functional-tests.md`
**writing script integration tests**
Script integration tests are built using `src/test/script_tests.cpp`:
1. Uncomment the line with `#define UPDATE_JSON_TESTS`
2. Add a new TestBuilder to the `script_build` test to cover your test case.
3. `make && ./src/test/test_bitcoin --run_test=script_tests`
4. Copy your newly generated test JSON from `/src/script_tests.json.gen` to `src/test/data/script_tests.json`.
Please commit your TestBuilder along with your generated test JSON and cleanup the uncommented #define before code review.
**testnet and regtest modes**
Run with the -testnet option to run with "play bitcoins" on the test network, if you
are testing multi-machine code that needs to operate across the internet.
If you are testing something that can run on one machine, run with the -regtest option.
In regression test mode, blocks can be created on-demand; see test/functional/ for tests
that run in -regtest mode.
**DEBUG_LOCKORDER**
Bitcoin Core is a multithreaded application, and deadlocks or other multithreading bugs
can be very difficult to track down. Compiling with -DDEBUG_LOCKORDER (configure
CXXFLAGS="-DDEBUG_LOCKORDER -g") inserts run-time checks to keep track of which locks
are held, and adds warnings to the debug.log file if inconsistencies are detected.
**Sanitizers**
Bitcoin can be compiled with various "sanitizers" enabled, which add
instrumentation for issues regarding things like memory safety, thread race
conditions, or undefined behavior. This is controlled with the
`--with-sanitizers` configure flag, which should be a comma separated list of
sanitizers to enable. The sanitizer list should correspond to supported
`-fsanitize=` options in your compiler. These sanitizers have runtime overhead,
so they are most useful when testing changes or producing debugging builds.
Some examples:
```bash
# Enable both the address sanitizer and the undefined behavior sanitizer
./configure --with-sanitizers=address,undefined
# Enable the thread sanitizer
./configure --with-sanitizers=thread
```
If you are compiling with GCC you will typically need to install corresponding
"san" libraries to actually compile with these flags, e.g. libasan for the
address sanitizer, libtsan for the thread sanitizer, and libubsan for the
undefined sanitizer. If you are missing required libraries, the configure script
will fail with a linker error when testing the sanitizer flags.
The test suite should pass cleanly with the `thread` and `undefined` sanitizers,
but there are a number of known problems when using the `address` sanitizer. The
address sanitizer is known to fail in
[sha256_sse4::Transform](/src/crypto/sha256_sse4.cpp) which makes it unusable
unless you also use `--disable-asm` when running configure. We would like to fix
sanitizer issues, so please send pull requests if you can fix any errors found
by the address sanitizer (or any other sanitizer).
Not all sanitizer options can be enabled at the same time, e.g. trying to build
with `--with-sanitizers=address,thread` will fail in the configure script as
these sanitizers are mutually incompatible. Refer to your compiler manual to
learn more about these options and which sanitizers are supported by your
compiler.
Additional resources:
* [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html)
* [LeakSanitizer](https://clang.llvm.org/docs/LeakSanitizer.html)
* [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html)
* [ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html)
* [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html)
* [GCC Instrumentation Options](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html)
* [Google Sanitizers Wiki](https://github.com/google/sanitizers/wiki)
* [Issue #12691: Enable -fsanitize flags in Travis](https://github.com/bitcoin/bitcoin/issues/12691)
Locking/mutex usage notes
-------------------------
The code is multi-threaded, and uses mutexes and the
LOCK/TRY_LOCK macros to protect data structures.
Deadlocks due to inconsistent lock ordering (thread 1 locks cs_main
and then cs_wallet, while thread 2 locks them in the opposite order:
result, deadlock as each waits for the other to release its lock) are
a problem. Compile with -DDEBUG_LOCKORDER to get lock order
inconsistencies reported in the debug.log file.
Re-architecting the core code so there are better-defined interfaces
between the various components is a goal, with any necessary locking
done by the components (e.g. see the self-contained CKeyStore class
and its cs_KeyStore lock for example).
Threads
-------
- ThreadScriptCheck : Verifies block scripts.
- ThreadImport : Loads blocks from blk*.dat files or bootstrap.dat.
- StartNode : Starts other threads.
- ThreadDNSAddressSeed : Loads addresses of peers from the DNS.
- ThreadMapPort : Universal plug-and-play startup/shutdown
- ThreadSocketHandler : Sends/Receives data from peers on port 8333.
- ThreadOpenAddedConnections : Opens network connections to added nodes.
- ThreadOpenConnections : Initiates new connections to peers.
- ThreadMessageHandler : Higher-level message handling (sending and receiving).
- DumpAddresses : Dumps IP addresses of nodes to peers.dat.
- ThreadFlushWalletDB : Close the wallet.dat file if it hasn't been used in 500ms.
- ThreadRPCServer : Remote procedure call handler, listens on port 8332 for connections and services them.
- BitcoinMiner : Generates bitcoins (if wallet is enabled).
- Shutdown : Does an orderly shutdown of everything.
Ignoring IDE/editor files
--------------------------
In closed-source environments in which everyone uses the same IDE it is common
to add temporary files it produces to the project-wide `.gitignore` file.
However, in open source software such as Bitcoin Core, where everyone uses
their own editors/IDE/tools, it is less common. Only you know what files your
editor produces and this may change from version to version. The canonical way
to do this is thus to create your local gitignore. Add this to `~/.gitconfig`:
```
[core]
excludesfile = /home/.../.gitignore_global
```
(alternatively, type the command `git config --global core.excludesfile ~/.gitignore_global`
on a terminal)
Then put your favourite tool's temporary filenames in that file, e.g.
```
# NetBeans
nbproject/
```
Another option is to create a per-repository excludes file `.git/info/exclude`.
These are not committed but apply only to one repository.
If a set of tools is used by the build system or scripts the repository (for
example, lcov) it is perfectly acceptable to add its files to `.gitignore`
and commit them.
Development guidelines
============================
A few non-style-related recommendations for developers, as well as points to
pay attention to for reviewers of Bitcoin Core code.
Wallet
-------
- Make sure that no crashes happen with run-time option `-disablewallet`.
- *Rationale*: In RPC code that conditionally uses the wallet (such as
`validateaddress`) it is easy to forget that global pointer `pwalletMain`
can be NULL. See `test/functional/disablewallet.py` for functional tests
exercising the API with `-disablewallet`
- Include `db_cxx.h` (BerkeleyDB header) only when `ENABLE_WALLET` is set
- *Rationale*: Otherwise compilation of the disable-wallet build will fail in environments without BerkeleyDB
General C++
-------------
- Assertions should not have side-effects
- - *Rationale*: Even though the source code is set to to refuse to compile
+ - *Rationale*: Even though the source code is set to refuse to compile
with assertions disabled, having side-effects in assertions is unexpected and
makes the code harder to understand
- If you use the `.h`, you must link the `.cpp`
- *Rationale*: Include files define the interface for the code in implementation files. Including one but
not linking the other is confusing. Please avoid that. Moving functions from
the `.h` to the `.cpp` should not result in build errors
- Use the RAII (Resource Acquisition Is Initialization) paradigm where possible. For example by using
`unique_ptr` for allocations in a function.
- *Rationale*: This avoids memory and resource leaks, and ensures exception safety
C++ data structures
--------------------
- Never use the `std::map []` syntax when reading from a map, but instead use `.find()`
- *Rationale*: `[]` does an insert (of the default element) if the item doesn't
exist in the map yet. This has resulted in memory leaks in the past, as well as
race conditions (expecting read-read behavior). Using `[]` is fine for *writing* to a map
- Do not compare an iterator from one data structure with an iterator of
another data structure (even if of the same type)
- *Rationale*: Behavior is undefined. In C++ parlor this means "may reformat
the universe", in practice this has resulted in at least one hard-to-debug crash bug
- Watch out for out-of-bounds vector access. `&vch[vch.size()]` is illegal,
including `&vch[0]` for an empty vector. Use `vch.data()` and `vch.data() +
vch.size()` instead.
- Vector bounds checking is only enabled in debug mode. Do not rely on it
- Make sure that constructors initialize all fields. If this is skipped for a
good reason (i.e., optimization on the critical path), add an explicit
comment about this
- *Rationale*: Ensure determinism by avoiding accidental use of uninitialized
values. Also, static analyzers balk about this.
- Use explicitly signed or unsigned `char`s, or even better `uint8_t` and
`int8_t`. Do not use bare `char` unless it is to pass to a third-party API.
This type can be signed or unsigned depending on the architecture, which can
lead to interoperability problems or dangerous conditions such as
out-of-bounds array accesses
- Prefer explicit constructions over implicit ones that rely on 'magical' C++ behavior
- *Rationale*: Easier to understand what is happening, thus easier to spot mistakes, even for those
that are not language lawyers
Strings and formatting
------------------------
- Use `std::string`, avoid C string manipulation functions
- *Rationale*: C++ string handling is marginally safer, less scope for
buffer overflows and surprises with `\0` characters. Also some C string manipulations
tend to act differently depending on platform, or even the user locale
- Use `ParseInt32`, `ParseInt64`, `ParseUInt32`, `ParseUInt64`, `ParseDouble` from `utilstrencodings.h` for number parsing
- *Rationale*: These functions do overflow checking, and avoid pesky locale issues
Variable names
--------------
The shadowing warning (`-Wshadow`) is enabled by default. It prevents issues rising
from using a different variable with the same name.
Please name variables so that their names do not shadow variables defined in the source code.
Threads and synchronization
----------------------------
- Build and run tests with `-DDEBUG_LOCKORDER` to verify that no potential
deadlocks are introduced. As of 0.12, this is defined by default when
configuring with `--enable-debug`
- When using `LOCK`/`TRY_LOCK` be aware that the lock exists in the context of
the current scope, so surround the statement and the code that needs the lock
with braces
OK:
```c++
{
TRY_LOCK(cs_vNodes, lockNodes);
...
}
```
Wrong:
```c++
TRY_LOCK(cs_vNodes, lockNodes);
{
...
}
```
Source code organization
--------------------------
- Implementation code should go into the `.cpp` file and not the `.h`, unless necessary due to template usage or
when performance due to inlining is critical
- *Rationale*: Shorter and simpler header files are easier to read, and reduce compile time
- Don't import anything into the global namespace (`using namespace ...`). Use
fully specified types such as `std::string`.
- *Rationale*: Avoids symbol conflicts
Header Inclusions
-----------------
- Header inclusions should use angle brackets (`#include <>`).
The include path should be relative to the `src` folder.
e.g.: `#include `
- Native C++ headers should be preferred over C compatibility headers.
e.g.: use `` instead of ``
- In order to make the code consistent, header files should be included in the following order, with each
section separated by a newline:
1. In a .cpp file, the associated .h is in first position. In a test source, this is the header file under test.
2. The project headers.
3. The test headers.
4. The 3rd party libraries headers. Different libraries should be in different sections.
5. The system libraries.
All headers should be lexically ordered inside their block.
GUI
-----
- Do not display or manipulate dialogs in model code (classes `*Model`)
- *Rationale*: Model classes pass through events and data from the core, they
should not interact with the user. That's where View classes come in. The converse also
holds: try to not directly access core data structures from Views.
- Avoid adding slow or blocking code in the GUI thread. In particular do not
add new `interface::Node` and `interface::Wallet` method calls, even if they
may be fast now, in case they are changed to lock or communicate across
processes in the future.
Prefer to offload work from the GUI thread to worker threads (see
`RPCExecutor` in console code as an example) or take other steps (see
https://doc.qt.io/archives/qq/qq27-responsive-guis.html) to keep the GUI
responsive.
- *Rationale*: Blocking the GUI thread can increase latency, and lead to
hangs and deadlocks.
Unit Tests
-----------
- Test suite naming convention: The Boost test suite in file
`src/test/foo_tests.cpp` should be named `foo_tests`. Test suite names must
be unique.
Subtrees
----------
Several parts of the repository are subtrees of software maintained elsewhere.
Some of these are maintained by active developers of Bitcoin Core, in which case changes should probably go
directly upstream without being PRed directly against the project. They will be merged back in the next
subtree merge.
Others are external projects without a tight relationship with our project. Changes to these should also
be sent upstream but bugfixes may also be prudent to PR against Bitcoin Core so that they can be integrated
quickly. Cosmetic changes should be purely taken upstream.
There is a tool in contrib/devtools/git-subtree-check.sh to check a subtree directory for consistency with
its upstream repository.
Current subtrees include:
- src/leveldb
- Upstream at https://github.com/google/leveldb ; Maintained by Google, but open important PRs to Core to avoid delay
- src/libsecp256k1
- Upstream at https://github.com/bitcoin-core/secp256k1/ ; actively maintaned by Core contributors.
- src/crypto/ctaes
- Upstream at https://github.com/bitcoin-core/ctaes ; actively maintained by Core contributors.
- src/univalue
- Upstream at https://github.com/jgarzik/univalue ; report important PRs to Core to avoid delay.
Git and GitHub tips
---------------------
- Github is not typically the source of truth for pull requests. See CONTRIBUTING.md for instructions
on setting up your repo correctly.
- Similarly, your git remote origin should be set to: `ssh://vcs@reviews.bitcoinabc.org:2221/source/bitcoin-abc.git`
instead of github.com. See CONTRIBUTING.md for details.
- For resolving merge/rebase conflicts, it can be useful to enable diff3 style using
`git config merge.conflictstyle diff3`. Instead of
<<<
yours
===
theirs
>>>
you will see
<<<
yours
|||
original
===
theirs
>>>
This may make it much clearer what caused the conflict. In this style, you can often just look
at what changed between *original* and *theirs*, and mechanically apply that to *yours* (or the other way around).
- When reviewing patches which change indentation in C++ files, use `git diff -w` and `git show -w`. This makes
the diff algorithm ignore whitespace changes. This feature is also available on github.com, by adding `?w=1`
at the end of any URL which shows a diff.
- When reviewing patches that change symbol names in many places, use `git diff --word-diff`. This will instead
of showing the patch as deleted/added *lines*, show deleted/added *words*.
- When reviewing patches that move code around, try using
`git diff --patience commit~:old/file.cpp commit:new/file/name.cpp`, and ignoring everything except the
moved body of code which should show up as neither `+` or `-` lines. In case it was not a pure move, this may
even work when combined with the `-w` or `--word-diff` options described above.
- When looking at other's pull requests, it may make sense to add the following section to your `.git/config`
file:
[remote "upstream-pull"]
fetch = +refs/pull/*:refs/remotes/upstream-pull/*
url = git@github.com:bitcoin/bitcoin.git
This will add an `upstream-pull` remote to your git repository, which can be fetched using `git fetch --all`
or `git fetch upstream-pull`. Afterwards, you can use `upstream-pull/NUMBER/head` in arguments to `git show`,
`git checkout` and anywhere a commit id would be acceptable to see the changes from pull request NUMBER.
RPC interface guidelines
--------------------------
A few guidelines for introducing and reviewing new RPC interfaces:
- Method naming: use consecutive lower-case names such as `getrawtransaction` and `submitblock`
- *Rationale*: Consistency with existing interface.
- Argument naming: use snake case `fee_delta` (and not, e.g. camel case `feeDelta`)
- *Rationale*: Consistency with existing interface.
- Use the JSON parser for parsing, don't manually parse integers or strings from
arguments unless absolutely necessary.
- *Rationale*: Introduces hand-rolled string manipulation code at both the caller and callee sites,
which is error prone, and it is easy to get things such as escaping wrong.
JSON already supports nested data structures, no need to re-invent the wheel.
- *Exception*: AmountFromValue can parse amounts as string. This was introduced because many JSON
parsers and formatters hard-code handling decimal numbers as floating point
values, resulting in potential loss of precision. This is unacceptable for
monetary values. **Always** use `AmountFromValue` and `ValueFromAmount` when
inputting or outputting monetary values. The only exceptions to this are
`prioritisetransaction` and `getblocktemplate` because their interface
is specified as-is in BIP22.
- Missing arguments and 'null' should be treated the same: as default values. If there is no
default value, both cases should fail in the same way. The easiest way to follow this
guideline is detect unspecified arguments with `params[x].isNull()` instead of
`params.size() <= x`. The former returns true if the argument is either null or missing,
while the latter returns true if is missing, and false if it is null.
- *Rationale*: Avoids surprises when switching to name-based arguments. Missing name-based arguments
are passed as 'null'.
- Try not to overload methods on argument type. E.g. don't make `getblock(true)` and `getblock("hash")`
do different things.
- *Rationale*: This is impossible to use with `bitcoin-cli`, and can be surprising to users.
- *Exception*: Some RPC calls can take both an `int` and `bool`, most notably when a bool was switched
to a multi-value, or due to other historical reasons. **Always** have false map to 0 and
true to 1 in this case.
- Don't forget to fill in the argument names correctly in the RPC command table.
- *Rationale*: If not, the call can not be used with name-based arguments.
- Set okSafeMode in the RPC command table to a sensible value: safe mode is when the
blockchain is regarded to be in a confused state, and the client deems it unsafe to
do anything irreversible such as send. Anything that just queries should be permitted.
- *Rationale*: Troubleshooting a node in safe mode is difficult if half the
RPCs don't work.
- Add every non-string RPC argument `(method, idx, name)` to the table `vRPCConvertParams` in `rpc/client.cpp`.
- *Rationale*: `bitcoin-cli` and the GUI debug console use this table to determine how to
convert a plaintext command line to JSON. If the types don't match, the method can be unusable
from there.
- A RPC method must either be a wallet method or a non-wallet method. Do not
introduce new methods such as `signrawtransaction` that differ in behavior
based on presence of a wallet.
- *Rationale*: as well as complicating the implementation and interfering
with the introduction of multi-wallet, wallet and non-wallet code should be
separated to avoid introducing circular dependencies between code units.
- Try to make the RPC response a JSON object.
- *Rationale*: If a RPC response is not a JSON object then it is harder to avoid API breakage if
new data in the response is needed.
- Wallet RPCs call BlockUntilSyncedToCurrentChain to maintain consistency with
`getblockchaininfo`'s state immediately prior to the call's execution. Wallet
RPCs whose behavior does *not* depend on the current chainstate may omit this
call.
- *Rationale*: In previous versions of Bitcoin Core, the wallet was always
in-sync with the chainstate (by virtue of them all being updated in the
same cs_main lock). In order to maintain the behavior that wallet RPCs
return results as of at least the highest best-known block an RPC
client may be aware of prior to entering a wallet RPC call, we must block
until the wallet is caught up to the chainstate as of the RPC call's entry.
This also makes the API much easier for RPC clients to reason about.
diff --git a/src/chain.cpp b/src/chain.cpp
index 6eba2cd035..46d0d892ba 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -1,193 +1,193 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include
/**
* CChain implementation
*/
void CChain::SetTip(CBlockIndex *pindex) {
if (pindex == nullptr) {
vChain.clear();
return;
}
vChain.resize(pindex->nHeight + 1);
while (pindex && vChain[pindex->nHeight] != pindex) {
vChain[pindex->nHeight] = pindex;
pindex = pindex->pprev;
}
}
CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
int nStep = 1;
std::vector vHave;
vHave.reserve(32);
if (!pindex) {
pindex = Tip();
}
while (pindex) {
vHave.push_back(pindex->GetBlockHash());
// Stop when we have added the genesis block.
if (pindex->nHeight == 0) {
break;
}
// Exponentially larger steps back, plus the genesis block.
int nHeight = std::max(pindex->nHeight - nStep, 0);
if (Contains(pindex)) {
// Use O(1) CChain index if possible.
pindex = (*this)[nHeight];
} else {
// Otherwise, use O(log n) skiplist.
pindex = pindex->GetAncestor(nHeight);
}
if (vHave.size() > 10) {
nStep *= 2;
}
}
return CBlockLocator(vHave);
}
const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
if (pindex == nullptr) {
return nullptr;
}
if (pindex->nHeight > Height()) {
pindex = pindex->GetAncestor(Height());
}
while (pindex && !Contains(pindex)) {
pindex = pindex->pprev;
}
return pindex;
}
CBlockIndex *CChain::FindEarliestAtLeast(int64_t nTime) const {
std::vector::const_iterator lower =
std::lower_bound(vChain.begin(), vChain.end(), nTime,
[](CBlockIndex *pBlock, const int64_t &time) -> bool {
return pBlock->GetBlockTimeMax() < time;
});
return (lower == vChain.end() ? nullptr : *lower);
}
/** Turn the lowest '1' bit in the binary representation of a number into a '0'.
*/
static inline int InvertLowestOne(int n) {
return n & (n - 1);
}
/** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
static inline int GetSkipHeight(int height) {
if (height < 2) {
return 0;
}
// Determine which height to jump back to. Any number strictly lower than
// height is acceptable, but the following expression seems to perform well
// in simulations (max 110 steps to go back up to 2**18 blocks).
return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1
: InvertLowestOne(height);
}
CBlockIndex *CBlockIndex::GetAncestor(int height) {
if (height > nHeight || height < 0) {
return nullptr;
}
CBlockIndex *pindexWalk = this;
int heightWalk = nHeight;
while (heightWalk > height) {
int heightSkip = GetSkipHeight(heightWalk);
int heightSkipPrev = GetSkipHeight(heightWalk - 1);
if (pindexWalk->pskip != nullptr &&
(heightSkip == height ||
(heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
heightSkipPrev >= height)))) {
// Only follow pskip if pprev->pskip isn't better than pskip->pprev.
pindexWalk = pindexWalk->pskip;
heightWalk = heightSkip;
} else {
assert(pindexWalk->pprev);
pindexWalk = pindexWalk->pprev;
heightWalk--;
}
}
return pindexWalk;
}
const CBlockIndex *CBlockIndex::GetAncestor(int height) const {
return const_cast(this)->GetAncestor(height);
}
void CBlockIndex::BuildSkip() {
if (pprev) {
pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
}
}
arith_uint256 GetBlockProof(const CBlockIndex &block) {
arith_uint256 bnTarget;
bool fNegative;
bool fOverflow;
bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
if (fNegative || fOverflow || bnTarget == 0) {
return 0;
}
// We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
- // as it's too large for a arith_uint256. However, as 2**256 is at least as
+ // as it's too large for an arith_uint256. However, as 2**256 is at least as
// large as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) /
// (bnTarget+1)) + 1, or ~bnTarget / (nTarget+1) + 1.
return (~bnTarget / (bnTarget + 1)) + 1;
}
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to,
const CBlockIndex &from,
const CBlockIndex &tip,
const Consensus::Params ¶ms) {
arith_uint256 r;
int sign = 1;
if (to.nChainWork > from.nChainWork) {
r = to.nChainWork - from.nChainWork;
} else {
r = from.nChainWork - to.nChainWork;
sign = -1;
}
r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
if (r.bits() > 63) {
return sign * std::numeric_limits::max();
}
return sign * r.GetLow64();
}
/**
* Find the last common ancestor two blocks have.
* Both pa and pb must be non null.
*/
const CBlockIndex *LastCommonAncestor(const CBlockIndex *pa,
const CBlockIndex *pb) {
if (pa->nHeight > pb->nHeight) {
pa = pa->GetAncestor(pb->nHeight);
} else if (pb->nHeight > pa->nHeight) {
pb = pb->GetAncestor(pa->nHeight);
}
while (pa != pb && pa && pb) {
pa = pa->pprev;
pb = pb->pprev;
}
// Eventually all chain branches meet at the genesis block.
assert(pa == pb);
return pa;
}
bool AreOnTheSameFork(const CBlockIndex *pa, const CBlockIndex *pb) {
// The common ancestor needs to be either pa (pb is a child of pa) or pb (pa
// is a child of pb).
const CBlockIndex *pindexCommon = LastCommonAncestor(pa, pb);
return pindexCommon == pa || pindexCommon == pb;
}
diff --git a/src/cuckoocache.h b/src/cuckoocache.h
index cbd93557b9..e8da673c95 100644
--- a/src/cuckoocache.h
+++ b/src/cuckoocache.h
@@ -1,461 +1,461 @@
// Copyright (c) 2016 Jeremy Rubin
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CUCKOOCACHE_H
#define BITCOIN_CUCKOOCACHE_H
#include
#include
#include
#include
#include
#include
#include
/** namespace CuckooCache provides high performance cache primitives
*
* Summary:
*
* 1) bit_packed_atomic_flags is bit-packed atomic flags for garbage collection
*
* 2) cache is a cache which is performant in memory usage and lookup speed. It
* is lockfree for erase operations. Elements are lazily erased on the next
* insert.
*/
namespace CuckooCache {
/**
* bit_packed_atomic_flags implements a container for garbage collection flags
* that is only thread unsafe on calls to setup. This class bit-packs collection
* flags for memory efficiency.
*
* All operations are std::memory_order_relaxed so external mechanisms must
* ensure that writes and reads are properly synchronized.
*
* On setup(n), all bits up to n are marked as collected.
*
* Under the hood, because it is an 8-bit type, it makes sense to use a multiple
* of 8 for setup, but it will be safe if that is not the case as well.
*/
class bit_packed_atomic_flags {
std::unique_ptr[]> mem;
public:
/** No default constructor as there must be some size */
bit_packed_atomic_flags() = delete;
/**
* bit_packed_atomic_flags constructor creates memory to sufficiently keep
* track of garbage collection information for size entries.
*
* @param size the number of elements to allocate space for
*
* @post bit_set, bit_unset, and bit_is_set function properly forall x. x <
* size
* @post All calls to bit_is_set (without subsequent bit_unset) will return
* true.
*/
explicit bit_packed_atomic_flags(uint32_t size) {
// pad out the size if needed
size = (size + 7) / 8;
mem.reset(new std::atomic[size]);
for (uint32_t i = 0; i < size; ++i)
mem[i].store(0xFF);
};
/**
* setup marks all entries and ensures that bit_packed_atomic_flags can
* store at least size entries
*
* @param b the number of elements to allocate space for
* @post bit_set, bit_unset, and bit_is_set function properly forall x. x <
* b
* @post All calls to bit_is_set (without subsequent bit_unset) will return
* true.
*/
inline void setup(uint32_t b) {
bit_packed_atomic_flags d(b);
std::swap(mem, d.mem);
}
/**
* bit_set sets an entry as discardable.
*
* @param s the index of the entry to bit_set.
* @post immediately subsequent call (assuming proper external memory
* ordering) to bit_is_set(s) == true.
*/
inline void bit_set(uint32_t s) {
mem[s >> 3].fetch_or(1 << (s & 7), std::memory_order_relaxed);
}
/**
* bit_unset marks an entry as something that should not be overwritten
*
* @param s the index of the entry to bit_unset.
* @post immediately subsequent call (assuming proper external memory
* ordering) to bit_is_set(s) == false.
*/
inline void bit_unset(uint32_t s) {
mem[s >> 3].fetch_and(~(1 << (s & 7)), std::memory_order_relaxed);
}
/**
* bit_is_set queries the table for discardability at s
*
* @param s the index of the entry to read.
* @returns if the bit at index s was set.
* */
inline bool bit_is_set(uint32_t s) const {
return (1 << (s & 7)) & mem[s >> 3].load(std::memory_order_relaxed);
}
};
/**
* cache implements a cache with properties similar to a cuckoo-set
*
* The cache is able to hold up to (~(uint32_t)0) - 1 elements.
*
* Read Operations:
* - contains(*, false)
*
* Read+Erase Operations:
* - contains(*, true)
*
* Erase Operations:
* - allow_erase()
*
* Write Operations:
* - setup()
* - setup_bytes()
* - insert()
* - please_keep()
*
* Synchronization Free Operations:
* - invalid()
* - compute_hashes()
*
* User Must Guarantee:
*
* 1) Write Requires synchronized access (e.g., a lock)
* 2) Read Requires no concurrent Write, synchronized with the last insert.
* 3) Erase requires no concurrent Write, synchronized with last insert.
* 4) An Erase caller must release all memory before allowing a new Writer.
*
*
* Note on function names:
* - The name "allow_erase" is used because the real discard happens later.
* - The name "please_keep" is used because elements may be erased anyways on
* insert.
*
* @tparam Element should be a movable and copyable type
* @tparam Hash should be a function/callable which takes a template parameter
* hash_select and an Element and extracts a hash from it. Should return
* high-entropy hashes for `Hash h; h<0>(e) ... h<7>(e)`.
*/
template class cache {
private:
/** table stores all the elements */
std::vector table;
/** size stores the total available slots in the hash table */
uint32_t size;
/**
* The bit_packed_atomic_flags array is marked mutable because we want
* garbage collection to be allowed to occur from const methods.
*/
mutable bit_packed_atomic_flags collection_flags;
/**
* epoch_flags tracks how recently an element was inserted into the cache.
* true denotes recent, false denotes not-recent. See insert() method for
* full semantics.
*/
mutable std::vector epoch_flags;
/**
- * epoch_heuristic_counter is used to determine when a epoch might be aged &
- * an expensive scan should be done. epoch_heuristic_counter is decremented
- * on insert and reset to the new number of inserts which would cause the
- * epoch to reach epoch_size when it reaches zero.
+ * epoch_heuristic_counter is used to determine when an epoch might be aged
+ * & an expensive scan should be done. epoch_heuristic_counter is
+ * decremented on insert and reset to the new number of inserts which would
+ * cause the epoch to reach epoch_size when it reaches zero.
*/
uint32_t epoch_heuristic_counter;
/**
* epoch_size is set to be the number of elements supposed to be in a epoch.
- * When the number of non-erased elements in a epoch exceeds epoch_size, a
+ * When the number of non-erased elements in an epoch exceeds epoch_size, a
* new epoch should be started and all current entries demoted. epoch_size
* is set to be 45% of size because we want to keep load around 90%, and we
* support 3 epochs at once -- one "dead" which has been erased, one "dying"
* which has been marked to be erased next, and one "living" which new
* inserts add to.
*/
uint32_t epoch_size;
/**
* hash_mask should be set to appropriately mask out a hash such that every
* masked hash is [0,size), eg, if floor(log2(size)) == 20, then hash_mask
* should be (1<<20)-1
*/
uint32_t hash_mask;
/**
* depth_limit determines how many elements insert should try to replace.
* Should be set to log2(n)
*/
uint8_t depth_limit;
/**
* hash_function is a const instance of the hash function. It cannot be
* static or initialized at call time as it may have internal state (such as
* a nonce).
*/
const Hash hash_function;
/**
* compute_hashes is convenience for not having to write out this expression
* everywhere we use the hash values of an Element.
*
* @param e the element whose hashes will be returned
* @returns std::array of deterministic hashes derived from e
*/
inline std::array compute_hashes(const Element &e) const {
return {{hash_function.template operator()<0>(e) & hash_mask,
hash_function.template operator()<1>(e) & hash_mask,
hash_function.template operator()<2>(e) & hash_mask,
hash_function.template operator()<3>(e) & hash_mask,
hash_function.template operator()<4>(e) & hash_mask,
hash_function.template operator()<5>(e) & hash_mask,
hash_function.template operator()<6>(e) & hash_mask,
hash_function.template operator()<7>(e) & hash_mask}};
}
/* end
* @returns a constexpr index that can never be inserted to */
constexpr uint32_t invalid() const { return ~(uint32_t)0; }
/**
* allow_erase marks the element at index n as discardable.
* Threadsafe without any concurrent insert.
* @param n the index to allow erasure of
*/
inline void allow_erase(uint32_t n) const { collection_flags.bit_set(n); }
/**
* please_keep marks the element at index n as an entry that should be kept.
* Threadsafe without any concurrent insert.
* @param n the index to prioritize keeping
*/
inline void please_keep(uint32_t n) const { collection_flags.bit_unset(n); }
/**
* epoch_check handles the changing of epochs for elements stored in the
* cache. epoch_check should be run before every insert.
*
* First, epoch_check decrements and checks the cheap heuristic, and then
* does a more expensive scan if the cheap heuristic runs out. If the
* expensive scan succeeds, the epochs are aged and old elements are
* allow_erased. The cheap heuristic is reset to retrigger after the worst
* case growth of the current epoch's elements would exceed the epoch_size.
*/
void epoch_check() {
if (epoch_heuristic_counter != 0) {
--epoch_heuristic_counter;
return;
}
// count the number of elements from the latest epoch which have not
// been erased.
uint32_t epoch_unused_count = 0;
for (uint32_t i = 0; i < size; ++i)
epoch_unused_count +=
epoch_flags[i] && !collection_flags.bit_is_set(i);
// If there are more non-deleted entries in the current epoch than the
// epoch size, then allow_erase on all elements in the old epoch (marked
// false) and move all elements in the current epoch to the old epoch
// but do not call allow_erase on their indices.
if (epoch_unused_count >= epoch_size) {
for (uint32_t i = 0; i < size; ++i)
if (epoch_flags[i])
epoch_flags[i] = false;
else
allow_erase(i);
epoch_heuristic_counter = epoch_size;
} else {
// reset the epoch_heuristic_counter to next do a scan when worst
// case behavior (no intermittent erases) would exceed epoch size,
// with a reasonable minimum scan size. Ordinarily, we would have to
// sanity check std::min(epoch_size, epoch_unused_count), but we
// already know that `epoch_unused_count < epoch_size` in this
// branch
epoch_heuristic_counter = std::max(
1u, std::max(epoch_size / 16, epoch_size - epoch_unused_count));
}
}
public:
/**
* You must always construct a cache with some elements via a subsequent
* call to setup or setup_bytes, otherwise operations may segfault.
*/
cache()
: table(), size(), collection_flags(0), epoch_flags(),
epoch_heuristic_counter(), epoch_size(), depth_limit(0),
hash_function() {}
/**
* setup initializes the container to store no more than new_size elements.
* setup rounds down to a power of two size.
*
* setup should only be called once.
*
* @param new_size the desired number of elements to store
* @returns the maximum number of elements storable
*/
uint32_t setup(uint32_t new_size) {
// depth_limit must be at least one otherwise errors can occur.
depth_limit = static_cast(
std::log2(static_cast(std::max((uint32_t)2, new_size))));
size = 1 << depth_limit;
hash_mask = size - 1;
table.resize(size);
collection_flags.setup(size);
epoch_flags.resize(size);
// Set to 45% as described above
epoch_size = std::max((uint32_t)1, (45 * size) / 100);
// Initially set to wait for a whole epoch
epoch_heuristic_counter = epoch_size;
return size;
}
/**
* setup_bytes is a convenience function which accounts for internal memory
* usage when deciding how many elements to store. It isn't perfect because
* it doesn't account for any overhead (struct size, MallocUsage, collection
* and epoch flags). This was done to simplify selecting a power of two
* size. In the expected use case, an extra two bits per entry should be
* negligible compared to the size of the elements.
*
* @param bytes the approximate number of bytes to use for this data
* structure.
* @returns the maximum number of elements storable (see setup()
* documentation for more detail)
*/
uint32_t setup_bytes(size_t bytes) {
return setup(bytes / sizeof(Element));
}
/**
* insert loops at most depth_limit times trying to insert a hash at various
* locations in the table via a variant of the Cuckoo Algorithm with eight
* hash locations.
*
* It drops the last tried element if it runs out of depth before
* encountering an open slot.
*
* Thus
*
* insert(x);
* return contains(x, false);
*
* is not guaranteed to return true.
*
* @param e the element to insert
* @post one of the following: All previously inserted elements and e are
* now in the table, one previously inserted element is evicted from the
* table, the entry attempted to be inserted is evicted.
*/
inline void insert(Element e) {
epoch_check();
uint32_t last_loc = invalid();
bool last_epoch = true;
std::array locs = compute_hashes(e);
// Make sure we have not already inserted this element.
// If we have, make sure that it does not get deleted.
for (uint32_t loc : locs)
if (table[loc] == e) {
please_keep(loc);
epoch_flags[loc] = last_epoch;
return;
}
for (uint8_t depth = 0; depth < depth_limit; ++depth) {
// First try to insert to an empty slot, if one exists
for (uint32_t loc : locs) {
if (!collection_flags.bit_is_set(loc)) continue;
table[loc] = std::move(e);
please_keep(loc);
epoch_flags[loc] = last_epoch;
return;
}
/**
* Swap with the element at the location that was not the last one
* looked at. Example:
*
* 1) On first iteration, last_loc == invalid(), find returns last,
* so last_loc defaults to locs[0].
* 2) On further iterations, where last_loc == locs[k], last_loc
* will go to locs[k+1 % 8], i.e., next of the 8 indices wrapping
* around to 0 if needed.
*
* This prevents moving the element we just put in.
*
* The swap is not a move -- we must switch onto the evicted element
* for the next iteration.
*/
last_loc =
locs[(1 + (std::find(locs.begin(), locs.end(), last_loc) -
locs.begin())) &
7];
std::swap(table[last_loc], e);
// Can't std::swap a std::vector::reference and a bool&.
bool epoch = last_epoch;
last_epoch = epoch_flags[last_loc];
epoch_flags[last_loc] = epoch;
// Recompute the locs -- unfortunately happens one too many times!
locs = compute_hashes(e);
}
}
/**
* contains iterates through the hash locations for a given element and
* checks to see if it is present.
*
* contains does not check garbage collected state (in other words, garbage
* is only collected when the space is needed), so:
*
* insert(x);
* if (contains(x, true))
* return contains(x, false);
* else
* return true;
*
* executed on a single thread will always return true!
*
* This is a great property for re-org performance for example.
*
* contains returns a bool set true if the element was found.
*
* @param e the element to check
* @param erase
*
* @post if erase is true and the element is found, then the garbage collect
* flag is set
* @returns true if the element is found, false otherwise
*/
inline bool contains(const Element &e, const bool erase) const {
std::array locs = compute_hashes(e);
for (uint32_t loc : locs) {
if (table[loc] == e) {
if (erase) {
allow_erase(loc);
}
return true;
}
}
return false;
}
};
} // namespace CuckooCache
#endif // BITCOIN_CUCKOOCACHE_H
diff --git a/src/httpserver.h b/src/httpserver.h
index 9d37ac12bd..60fb919418 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -1,159 +1,159 @@
// Copyright (c) 2015-2016 The Bitcoin Core developers
// Copyright (c) 2018 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_HTTPSERVER_H
#define BITCOIN_HTTPSERVER_H
#include
#include
#include
static const int DEFAULT_HTTP_THREADS = 4;
static const int DEFAULT_HTTP_WORKQUEUE = 16;
static const int DEFAULT_HTTP_SERVER_TIMEOUT = 30;
struct evhttp_request;
struct event_base;
class Config;
class CService;
class HTTPRequest;
/**
* Initialize HTTP server.
* Call this before RegisterHTTPHandler or EventBase().
*/
bool InitHTTPServer(Config &config);
/**
* Start HTTP server.
* This is separate from InitHTTPServer to give users race-condition-free time
* to register their handlers between InitHTTPServer and StartHTTPServer.
*/
bool StartHTTPServer();
/** Interrupt HTTP server threads */
void InterruptHTTPServer();
/** Stop HTTP server */
void StopHTTPServer();
/** Handler for requests to a certain HTTP path */
typedef std::function
HTTPRequestHandler;
/**
* Register handler for prefix.
* If multiple handlers match a prefix, the first-registered one will
* be invoked.
*/
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch,
const HTTPRequestHandler &handler);
/** Unregister handler for prefix */
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch);
/**
* Return evhttp event base. This can be used by submodules to
* queue timers or custom events.
*/
struct event_base *EventBase();
/**
* In-flight HTTP request.
* Thin C++ wrapper around evhttp_request.
*/
class HTTPRequest {
private:
struct evhttp_request *req;
bool replySent;
public:
explicit HTTPRequest(struct evhttp_request *req);
~HTTPRequest();
enum RequestMethod { UNKNOWN, GET, POST, HEAD, PUT, OPTIONS };
/** Get requested URI */
std::string GetURI();
/** Get CService (address:ip) for the origin of the http request */
CService GetPeer();
/** Get request method */
RequestMethod GetRequestMethod();
/**
* Get the request header specified by hdr, or an empty string.
- * Return an pair (isPresent,string).
+ * Return a pair (isPresent,string).
*/
std::pair GetHeader(const std::string &hdr);
/**
* Read request body.
*
* @note As this consumes the underlying buffer, call this only once.
* Repeated calls will return an empty string.
*/
std::string ReadBody();
/**
* Write output header.
*
* @note call this before calling WriteErrorReply or Reply.
*/
void WriteHeader(const std::string &hdr, const std::string &value);
/**
* Write HTTP reply.
* nStatus is the HTTP status code to send.
* strReply is the body of the reply. Keep it empty to send a standard
* message.
*
* @note Can be called only once. As this will give the request back to the
* main thread, do not call any other HTTPRequest methods after calling
* this.
*/
void WriteReply(int nStatus, const std::string &strReply = "");
};
/** Event handler closure */
class HTTPClosure {
public:
virtual void operator()() = 0;
virtual ~HTTPClosure() {}
};
/**
- * Event class. This can be used either as an cross-thread trigger or as a
+ * Event class. This can be used either as a cross-thread trigger or as a
* timer.
*/
class HTTPEvent {
public:
/**
* Create a new event.
* deleteWhenTriggered deletes this event object after the event is
* triggered (and the handler called)
* handler is the handler to call when the event is triggered.
*/
HTTPEvent(struct event_base *base, bool deleteWhenTriggered,
const std::function &handler);
~HTTPEvent();
/**
* Trigger the event. If tv is 0, trigger it immediately. Otherwise trigger
* it after the given time has elapsed.
*/
void trigger(struct timeval *tv);
bool deleteWhenTriggered;
std::function handler;
private:
struct event *ev;
};
#endif // BITCOIN_HTTPSERVER_H
diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h
index c4e7ac360b..7935a965a7 100644
--- a/src/leveldb/db/version_set.h
+++ b/src/leveldb/db/version_set.h
@@ -1,398 +1,398 @@
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// The representation of a DBImpl consists of a set of Versions. The
// newest version is called "current". Older versions may be kept
// around to provide a consistent view to live iterators.
//
// Each Version keeps track of a set of Table files per level. The
// entire set of versions is maintained in a VersionSet.
//
// Version,VersionSet are thread-compatible, but require external
// synchronization on all accesses.
#ifndef STORAGE_LEVELDB_DB_VERSION_SET_H_
#define STORAGE_LEVELDB_DB_VERSION_SET_H_
#include