aboutsummaryrefslogtreecommitdiff
path: root/doc/developer-notes.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/developer-notes.md')
-rw-r--r--doc/developer-notes.md221
1 files changed, 150 insertions, 71 deletions
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 2fa91ecb02..45e55b7c40 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -5,8 +5,10 @@ Developer Notes
**Table of Contents**
- [Developer Notes](#developer-notes)
- - [Coding Style](#coding-style)
- - [Doxygen comments](#doxygen-comments)
+ - [Coding Style (General)](#coding-style-general)
+ - [Coding Style (C++)](#coding-style-c)
+ - [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)
@@ -15,6 +17,7 @@ Developer Notes
- [DEBUG_LOCKORDER](#debug_lockorder)
- [Valgrind suppressions file](#valgrind-suppressions-file)
- [Compiling for test coverage](#compiling-for-test-coverage)
+ - [Performance profiling with perf](#performance-profiling-with-perf)
- [Locking/mutex usage notes](#lockingmutex-usage-notes)
- [Threads](#threads)
- [Ignoring IDE/editor files](#ignoring-ideeditor-files)
@@ -26,17 +29,20 @@ Developer Notes
- [Strings and formatting](#strings-and-formatting)
- [Variable names](#variable-names)
- [Threads and synchronization](#threads-and-synchronization)
+ - [Scripts](#scripts)
+ - [Shebang](#shebang)
- [Source code organization](#source-code-organization)
- [GUI](#gui)
- [Subtrees](#subtrees)
- [Git and GitHub tips](#git-and-github-tips)
- [Scripted diffs](#scripted-diffs)
+ - [Release notes](#release-notes)
- [RPC interface guidelines](#rpc-interface-guidelines)
<!-- markdown-toc end -->
-Coding Style
----------------
+Coding Style (General)
+----------------------
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
@@ -46,6 +52,9 @@ commits.
Do not submit patches solely to modify the style of existing code.
+Coding Style (C++)
+------------------
+
- **Indentation and whitespace rules** as specified in
[src/.clang-format](/src/.clang-format). You can use the provided
[clang-format-diff script](/contrib/devtools/README.md#clang-format-diffpy)
@@ -64,7 +73,7 @@ tool to clean up patches automatically before submission.
- **Symbol naming conventions**. These are preferred in new code, but are not
required when doing so would need changes to significant pieces of existing
code.
- - Variable and namespace names are all lowercase, and may use `_` to
+ - Variable (including function arguments) and namespace names are all lowercase, and may use `_` to
separate words (snake_case).
- Class member variables have a `m_` prefix.
- Global variables have a `g_` prefix.
@@ -113,10 +122,17 @@ public:
} // namespace foo
```
-Doxygen comments
------------------
+Coding Style (Python)
+---------------------
+
+Refer to [/test/functional/README.md#style-guidelines](/test/functional/README.md#style-guidelines).
+
+Coding Style (Doxygen-compatible comments)
+------------------------------------------
-To facilitate the generation of documentation, use doxygen-compatible comment blocks for functions, methods and fields.
+Bitcoin 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++
@@ -128,7 +144,7 @@ For example, to describe a function use:
*/
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.
+A complete list of `@xxx` commands can be found at http://www.doxygen.nl/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.
@@ -149,7 +165,7 @@ int var; //!< Detailed description after the member
```
or
-```cpp
+```c++
//! Description before the member
int var;
```
@@ -169,10 +185,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 http://www.doxygen.nl/manual/docblocks.html,
+but the above styles are favored.
+
+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.
-Documentation can be generated with `make docs` and cleaned up with `make clean-docs`.
+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
---------------------------
@@ -245,9 +266,54 @@ make cov
# A coverage report will now be accessible at `./test_bitcoin.coverage/index.html`.
```
+### Performance profiling with perf
+
+Profiling is a good way to get a precise idea of where time is being spent in
+code. One tool for doing profiling on Linux platforms is called
+[`perf`](http://www.brendangregg.com/perf.html), and has been integrated into
+the functional test framework. Perf can observe a running process and sample
+(at some frequency) where its execution is.
+
+Perf installation is contingent on which kernel version you're running; see
+[this StackExchange
+thread](https://askubuntu.com/questions/50145/how-to-install-perf-monitoring-tool)
+for specific instructions.
+
+Certain kernel parameters may need to be set for perf to be able to inspect the
+running process' stack.
+
+```sh
+$ sudo sysctl -w kernel.perf_event_paranoid=-1
+$ sudo sysctl -w kernel.kptr_restrict=0
+```
+
+Make sure you [understand the security
+trade-offs](https://lwn.net/Articles/420403/) of setting these kernel
+parameters.
+
+To profile a running bitcoind process for 60 seconds, you could use an
+invocation of `perf record` like this:
+
+```sh
+$ perf record \
+ -g --call-graph dwarf --per-thread -F 140 \
+ -p `pgrep bitcoind` -- sleep 60
+```
+
+You could then analyze the results by running
+
+```sh
+perf report --stdio | c++filt | less
+```
+
+or using a graphical tool like [Hotspot](https://github.com/KDAB/hotspot).
+
+See the functional test documentation for how to invoke perf within tests.
+
+
**Sanitizers**
-Bitcoin can be compiled with various "sanitizers" enabled, which add
+Bitcoin Core 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
@@ -412,6 +478,14 @@ Wallet
General C++
-------------
+For general C++ guidelines, you may refer to the [C++ Core
+Guidelines](https://isocpp.github.io/CppCoreGuidelines/).
+
+Common misconceptions are clarified in those sections:
+
+- Passing (non-)fundamental types in the [C++ Core
+ Guideline](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-conventional)
+
- Assertions should not have side-effects
- *Rationale*: Even though the source code is set to refuse to compile
@@ -429,6 +503,11 @@ General C++
- *Rationale*: This avoids memory and resource leaks, and ensures exception safety
+- Use `MakeUnique()` to construct objects owned by `unique_ptr`s
+
+ - *Rationale*: `MakeUnique` is concise and ensures exception safety in complex expressions.
+ `MakeUnique` is a temporary project local implementation of `std::make_unique` (C++14).
+
C++ data structures
--------------------
@@ -502,7 +581,7 @@ Strings and formatting
- *Rationale*: These functions do overflow checking, and avoid pesky locale issues.
- Avoid using locale dependent functions if possible. You can use the provided
- [`lint-locale-dependence.sh`](/contrib/devtools/lint-locale-dependence.sh)
+ [`lint-locale-dependence.sh`](/test/lint/lint-locale-dependence.sh)
to check for accidental use of locale dependent functions.
- *Rationale*: Unnecessary locale dependence can cause bugs that are very tricky to isolate and fix.
@@ -549,8 +628,8 @@ class AddressBookPage
Mode m_mode;
}
-AddressBookPage::AddressBookPage(Mode _mode) :
- m_mode(_mode)
+AddressBookPage::AddressBookPage(Mode _mode)
+ : m_mode(_mode)
...
```
@@ -587,6 +666,31 @@ TRY_LOCK(cs_vNodes, lockNodes);
}
```
+Scripts
+--------------------------
+
+### Shebang
+
+- Use `#!/usr/bin/env bash` instead of obsolete `#!/bin/bash`.
+
+ - [*Rationale*](https://github.com/dylanaraps/pure-bash-bible#shebang):
+
+ `#!/bin/bash` assumes it is always installed to /bin/ which can cause issues;
+
+ `#!/usr/bin/env bash` searches the user's PATH to find the bash binary.
+
+ OK:
+
+```bash
+#!/usr/bin/env bash
+```
+
+ Wrong:
+
+```bash
+#!/bin/bash
+```
+
Source code organization
--------------------------
@@ -690,16 +794,16 @@ Current subtrees include:
- Upstream at https://github.com/google/leveldb ; Maintained by Google, but
open important PRs to Core to avoid delay.
- **Note**: Follow the instructions in [Upgrading LevelDB](#upgrading-leveldb) when
- merging upstream changes to the leveldb subtree.
+ merging upstream changes to the LevelDB subtree.
- src/libsecp256k1
- - Upstream at https://github.com/bitcoin-core/secp256k1/ ; actively maintaned by Core contributors.
+ - Upstream at https://github.com/bitcoin-core/secp256k1/ ; actively maintained 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.
+ - Upstream at https://github.com/bitcoin-core/univalue ; actively maintained by Core contributors, deviates from upstream https://github.com/jgarzik/univalue
Upgrading LevelDB
---------------------
@@ -748,54 +852,6 @@ would be to revert the upstream fix before applying the updates to Bitcoin's
copy of LevelDB. In general you should be wary of any upstream changes affecting
what data is returned from LevelDB queries.
-Git and GitHub tips
----------------------
-
-- 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.
-
Scripted diffs
--------------
@@ -812,10 +868,34 @@ To create a scripted-diff:
- `-BEGIN VERIFY SCRIPT-`
- `-END VERIFY SCRIPT-`
-The scripted-diff is verified by the tool `test/lint/commit-script-check.sh`
+The scripted-diff is verified by the tool `test/lint/commit-script-check.sh`. The tool's default behavior when supplied
+with a commit is to verify all scripted-diffs from the beginning of time up to said commit. Internally, the tool passes
+the first supplied argument to `git rev-list --reverse` to determine which commits to verify script-diffs for, ignoring
+commits that don't conform to the commit message format described above.
+
+For development, it might be more convenient to verify all scripted-diffs in a range `A..B`, for example:
+
+```bash
+test/lint/commit-script-check.sh origin/master..HEAD
+```
Commit [`bb81e173`](https://github.com/bitcoin/bitcoin/commit/bb81e173) is an example of a scripted-diff.
+Release notes
+-------------
+
+Release notes should be written for any PR that:
+
+- introduces a notable new feature
+- fixes a significant bug
+- changes an API or configuration model
+- makes any other visible change to the end-user experience.
+
+Release notes should be added to a PR-specific release note file at
+`/doc/release-notes-<PR number>.md` to avoid conflicts between multiple PRs.
+All `release-notes*` files are merged into a single
+[/doc/release-notes.md](/doc/release-notes.md) file prior to the release.
+
RPC interface guidelines
--------------------------
@@ -880,8 +960,7 @@ A few guidelines for introducing and reviewing new RPC interfaces:
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.
+ introduce new methods 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