Skip to content
Snippets Groups Projects
Commit 997af1ac authored by SlowRiot's avatar SlowRiot :fire: Committed by freetrader
Browse files

Markdown code quality, 4 of 5

One of a multi-part series of changes to improve markdown code quality,
primarily driven by feedback from codeclimate's markdownlint plugin.
This MR resolves markdown issues with header styles:

- All files must begin with a top-level header
- There must only be one top-level header
- Header styles must be consistent throughout a file - both SETEXT and
  ATX styles are acceptable, but must be the same.  Where more than two header
  levels are present, SETEXT is replaced with ATX for consistency
  (as third-level and below headers don't exist in SETEXT style).
- No trailing punctuation in headers
- There must be whitespace surrounding a header

This also resolves the following miscellaneous issues:

- Fixing quotes for correct rendering

Test plan
---------

- review document changes
- Run codeclimate locally to verify rule violations have been addressed:

    docker run --interactive --tty --rm --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate analyze

- run ninja doc-html on master, take a backup, and run it again on this branch
- run recursive diff to verify no unexpected changes appear in the generated
  HTML for files where differences occur, compare changed locations in generated
  doc/html/index.html with a browser to content generated on master, and to
  content on https://docs.bitcoincashnode.org (not all changed documents are
  present there, the ones that are not can be treated as out of scope of this
  comparison)
parent ec910791
No related branches found
No related tags found
1 merge request!1340Markdown code quality, 4 of 5
Showing with 141 additions and 126 deletions
......@@ -15,6 +15,9 @@ rule 'MD013', :line_length => 300
#rule 'MD024', :allow_different_nesting => true
exclude_rule 'MD024'
# Trailing punctuation in header
exclude_rule 'MD026'
# ordered list item prefix
rule 'MD029', :style => 'ordered'
......
......@@ -131,8 +131,7 @@ Here are some handy links for development practices aligned with Bitcoin Cash No
- [Good Work, Great Work, and Right Work](https://forum.dlang.org/post/q7u6g1$94p$1@digitalmars.com)
- [Accelerate: The Science of Lean Software and DevOps](https://www.amazon.com/Accelerate-Software-Performing-Technology-Organizations/dp/1942788339)
Getting set up with the Bitcoin Cash Node Repository
----------------------------------------------
## Getting set up with the Bitcoin Cash Node Repository
1. Create an account at [https://gitlab.com](https://gitlab.com) if you don't have
one yet
......@@ -240,9 +239,7 @@ Getting set up with the Bitcoin Cash Node Repository
To run benchmarks, see [Benchmarking](doc/benchmarking.md).
Working with The Bitcoin Cash Node Repository
---------------------------------------------
## Working with The Bitcoin Cash Node Repository
A typical workflow would be:
......@@ -285,23 +282,20 @@ please contact our developers and they will help you decide.
later), as this will help cut your re-build times from several minutes to under
a minute, in many cases.
What to work on
---------------
## What to work on
If you are looking for a useful task to contribute to the project, a good place
to start is the list of issues at [https://gitlab.com/bitcoin-cash-node/bitcoin-cash-node/-/issues](https://gitlab.com/bitcoin-cash-node/bitcoin-cash-node/-/issues)
Look for issues marked with a label 'good-first-issue'.
Copyright
---------
## Copyright
By contributing to this repository, you agree to license your work under the
MIT license unless specified otherwise in `contrib/debian/copyright` or at
the top of the file itself. Any work contributed where you are not the original
author must contain its license header with the original author(s) and source.
Disclosure Policy
-----------------
## Disclosure Policy
See [DISCLOSURE_POLICY](DISCLOSURE_POLICY.md).
......@@ -4,12 +4,12 @@ This document describes how to install Bitcoin Cash Node.
**Please ensure to back up your wallet files before you run any new client.**
# Downloading Bitcoin Cash Node
## Downloading Bitcoin Cash Node
If you just want to run the Bitcoin Cash Node software go to the
[Download](https://bitcoincashnode.org/download.html) page and get the relevant
If you just want to run the Bitcoin Cash Node software go to the
[Download](https://bitcoincashnode.org/download.html) page and get the relevant
files for your system.
# Building Bitcoin Cash Node
## Building Bitcoin Cash Node
See `doc/build-*.md` for instructions on building the Bitcoin Cash Node software.
......@@ -20,7 +20,7 @@ split on August 1, 2017. Bitcoin Cash and the Bitcoin Core version of Bitcoin
share the same transaction history up until the split.
What is Bitcoin Cash Node?
--------------------
--------------------------
[Bitcoin Cash Node](https://www.bitcoincashnode.org) is the name of open-source
software which enables the use of Bitcoin Cash. It is a descendant of the
......
Repository Tools
---------------------
# Contrib tools #
## Repository Tools ##
### [Developer tools](devtools/) ###
......@@ -18,14 +19,13 @@ A Linux bash script that will set up traffic control (tc) to limit the outgoing
Utility to generate the pnSeed[] array that is compiled into the client.
Build Tools and Keys
---------------------
## Build Tools and Keys ##
### [Gitian-descriptors](gitian-descriptors/) ###
Notes on getting Gitian builds up and running using KVM.
### [Gitian-keys](gitian-signing/)
### [Gitian-keys](gitian-signing/) ###
PGP keys used for signing Bitcoin Cash Node [Gitian release](../doc/release-process.md) results.
......@@ -37,8 +37,8 @@ Scripts and notes for Mac builds.
Script for running full Gitian builds.
Test and Verify Tools
---------------------
## Test and Verify Tools ##
### [TestGen](testgen/) ###
Utilities to generate test vectors for the data-driven Bitcoin tests.
Contents
========
# Contents
This directory contains tools for developers working on this repository.
copyright\_header.py
====================
## copyright\_header.py
Provides utilities for managing copyright headers of `The Bitcoin developers`
in repository source files. It has three subcommands:
......@@ -17,15 +15,13 @@ $ ./copyright_header.py insert <file>
Running these subcommands without arguments displays a usage string.
copyright\_header.py report \<base\_directory\> [verbose]
---------------------------------------------------------
### copyright\_header.py report \<base\_directory\> [verbose]
Produces a report of all copyright header notices found inside the source files
of a repository. Useful to quickly visualize the state of the headers.
Specifying `verbose` will list the full filenames of files of each category.
copyright\_header.py update \<base\_directory\> [verbose]
---------------------------------------------------------
### copyright\_header.py update \<base\_directory\> [verbose]
Updates all the copyright headers of `The Bitcoin developers` which were changed
in a year more recent than is listed. For example:
......@@ -57,8 +53,7 @@ will be updated to:
where the update is appropriate.
copyright\_header.py insert \<file\>
------------------------------------
### copyright\_header.py insert \<file\>
Inserts a copyright header for `The Bitcoin developers` at the top of the file
in either Python or C++ style as determined by the file extension. If the file
......@@ -73,19 +68,16 @@ year rather than two hyphenated years.
If the file already has a copyright for `The Bitcoin developers`, the script
will exit.
optimize-pngs.py
================
## optimize-pngs.py
A script to optimize png files in the bitcoin
repository (requires pngcrush).
security-check.py and test-security-check.py
============================================
## security-check.py and test-security-check.py
Perform basic ELF security checks on a series of executables.
symbol-check.py
===============
## symbol-check.py
A script to check that the (Linux) executables produced by gitian only contain
allowed gcc, glibc and libstdc++ version symbols. This makes sure they are
......@@ -108,8 +100,7 @@ If there are 'unsupported' symbols, the return value will be 1 a list like this
.../64/test_bitcoin: symbol _ZNSt8__detail15_List_nod from unsupported version GLIBCXX_3.4.15
```
circular-dependencies.py
========================
## circular-dependencies.py
Run this script from the root of the source tree (`src/`) to find circular dependencies in the source code.
This looks only at which files include other files, treating the `.cpp` and `.h` file as one unit.
......
# Contributed scripts
Sample configuration files for:
```
......
### QoS (Quality of service) ###
# QoS (Quality of service) #
This is a Linux bash script that will set up tc to limit the outgoing bandwidth for connections to the Bitcoin network. It limits outbound TCP traffic with a source or destination port of 8333, but not if the destination IP is within a LAN.
......
### Usage
# Dependencies
## Usage
To build dependencies for the current architecture + OS:
......@@ -61,13 +63,13 @@ from the project root):
No other options are needed, the paths are automatically configured.
### Install the required dependencies: Ubuntu & Debian
## Install the required dependencies: Ubuntu & Debian
#### Common to all arch/OS
### Common to all arch/OS
sudo apt-get install build-essential autoconf automake cmake curl git libtool ninja-build patch pkg-config python3
#### For macOS cross compilation
### For macOS cross compilation
Install the following packages:
......@@ -77,11 +79,11 @@ Obtain the same SDK packge that is used in the gitian build (refer to `gitian-bu
Create an `SDKs` folder within the `depends` folder, if it does not already exist.
Unpack the SDK tarball there.
#### For Win64 cross compilation
### For Win64 cross compilation
- see [build-windows.md](../doc/build-windows.md#cross-compilation-for-ubuntu-and-windows-subsystem-for-linux)
#### For Linux cross compilation
### For Linux cross compilation
Common linux dependencies:
......@@ -106,8 +108,7 @@ For linux AARCH64 cross compilation:
sudo apt-get install g++-aarch64-linux-gnu
### Dependency Options
## Dependency Options
The following can be set when running make: make FOO=bar
......@@ -146,7 +147,7 @@ Additional targets:
download-linux: run 'make download-linux' to fetch all sources needed for linux builds
build-all: build the dependencies for all the arch/OS
### Other documentation
## Other documentation
- [description.md](description.md): General description of the depends system
- [packages.md](packages.md): Steps for adding packages
This is a system of building and caching dependencies necessary for building Bitcoin.
# Dependencies
This is a system of building and caching dependencies necessary for building Bitcoin.
There are several features that make it different from most similar systems:
### It is designed to be builder and host agnostic
## It is designed to be builder and host agnostic
In theory, binaries for any target OS/architecture can be created, from a
builder running any OS/architecture. In practice, build-side tools must be
......@@ -9,28 +11,28 @@ specified when the defaults don't fit, and packages must be amended to work
on new hosts. For now, a build architecture of x86_64 is assumed, either on
Linux or macOS.
### No reliance on timestamps
## No reliance on timestamps
File presence is used to determine what needs to be built. This makes the
results distributable and easily digestable by automated builders.
### Each build only has its specified dependencies available at build-time.
## Each build only has its specified dependencies available at build-time
For each build, the sysroot is wiped and the (recursive) dependencies are
installed. This makes each build deterministic, since there will never be any
unknown files available to cause side-effects.
### Each package is cached and only rebuilt as needed.
## Each package is cached and only rebuilt as needed
Before building, a unique build-id is generated for each package. This id
consists of a hash of all files used to build the package (Makefiles, packages,
etc), and as well as a hash of the same data for each recursive dependency. If
any portion of a package's build recipe changes, it will be rebuilt as well as
any other package that depends on it. If any of the main makefiles (Makefile,
any other package that depends on it. If any of the main makefiles (Makefile,
funcs.mk, etc) are changed, all packages will be rebuilt. After building, the
results are cached into a tarball that can be re-used and distributed.
### Package build results are (relatively) deterministic.
## Package build results are (relatively) deterministic
Each package is configured and patched so that it will yield the same
build-results with each consequent build, within a reasonable set of
......@@ -39,13 +41,13 @@ beyond the scope of this system. Additionally, the toolchain itself must be
capable of deterministic results. When revisions are properly bumped, a cached
build should represent an exact single payload.
### Sources are fetched and verified automatically
## Sources are fetched and verified automatically
Each package must define its source location and checksum. The build will fail
if the fetched source does not match. Sources may be pre-seeded and/or cached
as desired.
### Self-cleaning
## Self-cleaning
Build and staging dirs are wiped after use, and any previous version of a
cached result is removed following a successful build. Automated builders
......
# Packages
Each recipe consists of 3 main parts: defining identifiers, setting build
variables, and defining build commands.
......@@ -50,8 +52,8 @@ These variables are optional:
Any extra files that will be fetched via $(package)_fetch_cmds. These are
specified so that they can be fetched and verified via 'make download'.
## Build Variables
## Build Variables:
After defining the main identifiers, build variables may be added or customized
before running the build commands. They should be added to a function called
$(package)_set_vars. For example:
......@@ -102,7 +104,7 @@ These will be used in addition to the options that do not specify
debug/release. All builds are considered to be release unless DEBUG=1 is set by
the user. Other variables may be defined as needed.
## Build commands:
## Build commands
For each build, a unique build dir and staging dir are created. For example,
`work/build/mylib/1.0-1adac830f6e` and `work/staging/mylib/1.0-1adac830f6e`.
......@@ -153,7 +155,7 @@ Most autotools projects can be properly staged using:
$(MAKE) DESTDIR=$($(package)_staging_dir) install
## Build outputs:
## Build outputs
In general, the output of a depends package should not contain any libtool
archives. Instead, the package should output `.pc` (`pkg-config`) files where
......@@ -165,7 +167,7 @@ From the [Gentoo Wiki entry](https://wiki.gentoo.org/wiki/Project:Quality_Assura
> creates. This leads to massive overlinking, which is toxic to the Gentoo
> ecosystem, as it leads to a massive number of unnecessary rebuilds.
## Secondary dependencies:
## Secondary dependencies
Secondary dependency packages relative to the bitcoin binaries/libraries (i.e.
those not in `ALLOWED_LIBRARIES` in `contrib/devtools/symbol-check.py`) don't
......
Bitcoin Cash Node Setup
=======================
# Bitcoin Cash Node Setup
Bitcoin Cash Node is a node and wallet implementation for the Bitcoin Cash network.
It downloads and, by default, stores the entire history of Bitcoin Cash
......@@ -9,8 +8,7 @@ can take anywhere from a few hours to a day or more.
To download Bitcoin Cash Node, visit [bitcoincashnode.org](https://bitcoincashnode.org/).
Verify
---------------------
## Verify
If you download the associated signature files with the binaries from the above link,
you can verify the integrity of the binaries by following these instructions, replacing
......@@ -47,8 +45,7 @@ you should `gpg --sign-key <signer key>` for each release signer key and rerun
the above script (there should be no warnings the second time). If the keys change
unexpectedly, the presence of those warnings should be heeded with extreme caution.
Running
---------------------
## Running
The following are some helpful notes on how to run Bitcoin Cash Node on your
native platform.
......@@ -68,7 +65,7 @@ Unpack the files into a directory, and then run `bitcoin-qt.exe`.
Drag `bitcoin-cash-node` to your applications folder, and then run `bitcoin-cash-node`.
### Need Help?
## Help
- Ask for help on the [Bitcoin Cash Node Subreddit](https://www.reddit.com/r/bitcoincashnode/).
Deterministic macOS DMG Notes.
# Deterministic macOS DMG Notes
Working macOS DMGs are created in Linux by combining a recent clang,
the Apple binutils (ld, ar, etc) and DMG authoring tools.
......
Unauthenticated REST Interface
==============================
# Unauthenticated REST Interface
The REST API can be enabled with the `-rest` option.
The interface runs on the same port as the JSON-RPC interface, by default:
- port 8332 for mainnet,
- port 18332 for testnet,
- port 28332 for testnet4,
- port 38332 for scalenet,
- port 18443 for regtest.
Supported API
-------------
## Supported API
### Transactions
......@@ -112,8 +111,8 @@ Only supports JSON as output format.
Returns transactions in the TX mempool.
Only supports JSON as output format.
Risks
-------------
## Risks
Running a web browser on the same node with a REST enabled bitcoind can be a risk.
Accessing prepared XSS websites could read out tx/block data of your node by placing
links like `<script src="http://127.0.0.1:8332/rest/tx/1234567890.json">` which
......
# Assets Attribution
The list of assets used in the bitcoin source and their attribution can now be
found in [contrib/debian/copyright](/contrib/debian/copyright).
......@@ -27,48 +27,71 @@ You will need to create a GitLab account if you don't have one (it's free to do
The following are rules and should always be followed.
**Rule 0**: If it seems wrong to follow a rule in some instance, query back with
### Rule 0
If it seems wrong to follow a rule in some instance, query back with
the maintainer about whether the process needs adjustment.
**General Rule 1**: Any exceptions to following the rules shall always be documented
### General Rule 1
Any exceptions to following the rules shall always be documented
by a comment on GitLab. If you see a rule violation, ask the person (ping them on
GL) to ask them to comment and explain why they did what they did.
**General Rule 2**: For developers, when approving a merge request ("Approve" button),
### General Rule 2
For developers, when approving a merge request ("Approve" button),
a comment must be left on what basis the approval is made. It can be in the terse
form (ref. "Code review lingo") or in a more descriptive comment.
**General Rule 3**: Every MR shall have a test plan accompanying it its description.
### General Rule 3
Every MR shall have a test plan accompanying it its description.
Example of a (very simple) test plan:
_"Added unittest. Run `ninja check-all`."_
> "Added unittest. Run `ninja check-all`."
**General Rule 4**: The contributor must execute his own test plan, or if unable
to do so for whatever reason, explicitly transfer this responsibility to the maintainer.
### General Rule 4
The contributor must execute his own test plan, or if unable
to do so for whatever reason, explicitly transfer this responsibility to the maintainer.
## Rules for maintainers
**Maintainer Rule 1**: Maintainers shall only merge requests which have been code
### Maintainer Rule 1
Maintainers shall only merge requests which have been code
reviewed.
**Maintainer Rule 2**: Consensus changes shall be manually tested and verified
### Maintainer Rule 2
Consensus changes shall be manually tested and verified
before merge.
**Maintainer Rule 3**: Maintainers shall not merge their own changes (unless with
### Maintainer Rule 3
Maintainers shall not merge their own changes (unless with
exceptions)
**Maintainer Rule 4**: All threads on the merge request must be marked as resolved
### Maintainer Rule 4
All threads on the merge request must be marked as resolved
prior to merging.
**Maintainer Rule 5**: MRs with "HODL" label set shall not be merged - maintainers
### Maintainer Rule 5
MRs with "HODL" label set shall not be merged - maintainers
must follow up status
**Maintainer Rule 6**: Any change to consensus code shall be treated as non-trivial
### Maintainer Rule 6
Any change to consensus code shall be treated as non-trivial
and trigger the minimum review period in Guideline 4 before merging (unless it is
a noted emergency)
**Maintainer Rule 7**: A non-trivial change to critical code must be approved by at
### Maintainer Rule 7
A non-trivial change to critical code must be approved by at
least two maintainers. Critical code is code where a bug could have severe
consequences for users if it is not spotted during review, including but not
limited to consensus rules (risk of acceptance or creation of invalid blocks)
......@@ -83,33 +106,42 @@ merge request in its configuration to 2.
The following are guidelines and should be followed if possible.
**Guideline 1**: Assign issues to yourself when starting to work on them, if they
### Guideline 1
Assign issues to yourself when starting to work on them, if they
are unassigned. You don't need anyone's permission, but if it's an issue with past
history, it is polite to query first if there is a chance your action might get
in the way of someone.
**Guideline 2**: If an issue is assigned to someone else but you can do some task
### Guideline 2
If an issue is assigned to someone else but you can do some task
that you think is helpful, you can do so without assigning it to yourself, or co-assigning
it to yourself to indicate that you are also working on something related to that
issue. You can also query (via GitLab or otherwise) with the current Assignee whether
they want to hand it over to you, in case they are currently inconvenienced or blocked
from progressing it.
**Guideline 3**: Use appropriate project checklists when reviewing anything. If
### Guideline 3
Use appropriate project checklists when reviewing anything. If
you don't find a checklist, bug the maintainers to provide you one.
**Guideline 4**: For non-trivial contributions, merge requests that are not
### Guideline 4
For non-trivial contributions, merge requests that are not
work-in-progress should sit for at least 36 hours to ensure that contributors in
other timezones have time to review. Consideration should be given to weekends
and other holiday periods to ensure active committers all have reasonable time to
become involved in the discussion and review process if they wish.
**Guideline 5**: It is asked that maintainers (active committers) indicate their
### Guideline 5
It is asked that maintainers (active committers) indicate their
unavailability when they know they will be absent from the project for longer periods
of time. This helps keep momentum going, allowing others to step in quicker to help
land merge requests.
### Code review lingo
Commonly used lingo when reviewing a MR
......@@ -127,10 +159,9 @@ Commonly used lingo when reviewing a MR
- NACK - "I don't approve of this change because of review or verification issues
with it"
### Use of labels, commit tags and "Draft"
**Labels**
#### Labels
GitLab has a facility for decorating issues and Merge Requests with labels. Please
see below for a list of known labels.
......@@ -144,7 +175,7 @@ labels on issues may change during lifetime of an issue / MR.
Anyone can set labels (add new, change, remove) at any time, the GitLab system
records all these label changes so it remains traceable who did what, when.
**Tags**
#### Tags
Committers can add prefix tags to their commit messages and MR titles to provide
brief visual summary of their committed or proposed changes.
......@@ -153,7 +184,7 @@ These tags have no special meaning to GitLab (at least not yet) and are simply f
human consumption at this stage.They are not well standardized, but below you will
find a section documenting some better known commit tags.
**Draft**
#### Draft
When a merge requested is prefixed by "Draft:", GitLab blocks merging of the MR.
......
Developer Notes
===============
# Developer Notes
Coding Style
---------------
## Coding Style
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
......@@ -100,8 +98,7 @@ public:
} // namespace foo
```
Doxygen comments
-----------------
## Doxygen comments
To facilitate the generation of documentation, use doxygen-compatible comment
blocks for functions, methods and fields.
......@@ -179,8 +176,7 @@ doxygen doc/Doxyfile
# output goes to doc/doxygen/html/
```
Development tips and tricks
---------------------------
## Development tips and tricks
### Compiling for debugging
......@@ -382,8 +378,7 @@ Additional resources:
- [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
-------------------------
## Locking/mutex usage notes
The code is multi-threaded, and uses mutexes and the
`LOCK` and `TRY_LOCK` macros to protect data structures.
......@@ -399,8 +394,7 @@ between the various components is a goal, with any necessary locking
done by the components (e.g. see the self-contained `CBasicKeyStore` class
and its `cs_KeyStore` lock for example).
Threads
-------
## Threads
- ThreadScriptCheck : Verifies block scripts.
- ThreadImport : Loads blocks from blk*.dat files or bootstrap.dat.
......@@ -416,8 +410,7 @@ Threads
connections and services them.
- Shutdown : Does an orderly shutdown of everything.
Ignoring IDE/editor files
--------------------------
## 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.
......@@ -449,8 +442,7 @@ 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
----------------------
## Development guidelines
A few non-style-related recommendations for developers, as well as points to
pay attention to for reviewers of Bitcoin Cash Node code.
......@@ -788,8 +780,7 @@ would be to revert the upstream fix before applying the updates to Bitcoin
Cash Node's copy of LevelDB. In general you should be wary of any upstream
changes affecting what data is returned from LevelDB queries.
Git and GitLab tips
---------------------
## Git and GitLab tips
- See CONTRIBUTING.md for instructions on setting up your repo correctly.
......@@ -853,8 +844,7 @@ Git and GitLab tips
`git checkout` and anywhere a commit id would be acceptable to see the changes
from merge request NUMBER.
RPC interface guidelines
--------------------------
## RPC interface guidelines
A few guidelines for introducing and reviewing new RPC interfaces:
......
Files
=====
* banlist.dat: stores the IPs/Subnets of banned nodes
* bitcoin.conf: contains configuration settings for bitcoind or bitcoin-qt
......
......@@ -326,11 +326,11 @@ Helpers for script.py
Helper functions for creating blocks and transactions.
# Running functional tests in an emulator
## Running functional tests in an emulator
Cross-compiled binaries can be tested with qemu or wine.
## AArch64
### AArch64
Prerequisite
......
Fuzz-testing Bitcoin Cash Node
==============================
# Fuzz-testing Bitcoin Cash Node
A special test harness in `src/test/fuzz/` is provided for each fuzz target to
provide an easy entry point for fuzzers and the like. In this document we'll
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment