# DragonX Release Process

## High-Level Philosophy

Beware of making high-risk changes (such as consensus changes, p2p layer changes and wallet/transaction changes) too close to a new release, because they will not get as much testing as they should. Don't merge large branches which haven't undergone lots of testing just before a release.

It is best to keep doc/relnotes/README.md up to date as changes and bug fixes are made. It's more work to summarize all changes and bugfixes just before the release.

## Branch model

Development happens on the `dev` branch. Releases are cut on the default branch, `master`. Code changes should land on `dev` first and undergo testing before being merged into `master`.

## Check for changes on master that should be on dev

Occasionally trivial changes are made directly on the `master` branch, such as documentation changes. In theory, no code changes should happen on `master` without being on `dev` first, but it's better to be safe than sorry. We want the `dev` branch which undergoes testing to be as close as possible to what the `master` branch will become, so we don't want to merge `dev` into `master` and just assume everything works. So it's best to merge the `master` branch into `dev` just before merging the `dev` branch into `master`.

To check if the `master` branch has any changes that the `dev` branch does not:

```
# this assumes you are working with https://git.dragonx.is/DragonX/dragonx as your remote
git checkout dev
git pull                  # make sure dev is up to date
git checkout master
git pull                  # make sure master is up to date
git diff dev...master     # look at the set of changes which exist in master but not dev
```

If the last command has no output, congrats, there is nothing to do. If the last command has output, then you should merge `master` into `dev`:

```
git checkout dev
git merge master
git push origin dev
```

Use the `--no-ff` flag when merging `dev` into `master` for a release (see below). The `--no-ff` flag makes sure to make a merge commit, no matter what, even if a "fast forward" could be done. For those in the future looking back, it's much better to see evidence of when branches were merged.


### Git Issues

Look for Git issues that should be fixed in the next release. Especially low-risk and simple things, like documentation changes, improvements to error messages and RPC help output.

### Pre-release checklist:
  * Is this release changing consensus rules? Definitely update protocol version.

### Protocol Safety Checks:

  * Does `PROTOCOL_VERSION` in src/version.h need to be increased?
    * All releases with a consensus change should increase the value by 1
    * All releases with a large change to the networking (P2P) layer should increase the value by 1
    * This identifies a nodes protocol version to all other peers it connects to.
  * Does `MIN_PEER_PROTO_VERSION` in src/version.h need to change?
    * If it does, new nodes will not be able to talk to nodes with a version less than `MIN_PROTO_VERSION`
  * The main use of these is for newer nodes that know they do not want to talk to older nodes to prevent connecting to older nodes efficiently
  * For instance, when a new release has different consensus rules than older nodes, `MIN_PROTO_VERSION` prevents wasting lots of network bandwidth talking to incompatible nodes which will eventually be banned for disagreeing on consensus rules

## Release dependencies

Install deps on Linux:

	apt-get install help2man devscripts

## Release process
 - If new seeds are being added or seeds are changing:
   - Edit contrib/seeds/nodes_main.txt
   - Run "make seeds"
   - Commit the result
 - Update version in configure.ac and src/clientversion.h to update the dragonxd version
   - **The new version MUST be higher than every version already tagged**, including tags that were never built or published. Check with `git tag -l --sort=-v:refname | head`. Two trees stamped with the same `CLIENT_VERSION` are indistinguishable on the wire, in `getnetworkinfo`, and to the wallet's in-app updater — and a published archive that does not match its tag destroys the only provenance check users have.
   - In src/clientversion.h you update `CLIENT_VERSION_*` variables. Usually you will just update `CLIENT_VERSION_REVISION`
   - If there is a consensus change, it may be a good idea to update `CLIENT_VERSION_MINOR` or `CLIENT_VERSION_MAJOR`
   - To make a pre-release "beta" you can modify `CLIENT_VERSION_BUILD` but that is rarely done.
   - A `CLIENT_VERSION_BUILD` of 50 means "actual non-beta release"
   - Make sure to keep the values in configure.ac and src/clientversion.h the same. The variables are prefixed wth an underscore in configure.ac
 - Run `./util/gen-manpages.sh`, commit + push results
   - There is a hack in the script where you can hardcode a version number if dragonxd isn't compiled on this machine
   - Comment out the version line and uncomment the line above it with a hardcoded version number
   - PROTIP: Man page creation must be done after updating the version number and recompiling and before Debian package creation
   - TODO: How to regenerate html man pages?
 - Update checkpoints in src/chainparams.cpp via util/checkpoints.pl
   - Run "./util/checkpoints.pl help" to get example usage
   - dragonxd must be running to run this script, since it uses dragonx-cli to get the data
   - Look for the line which marks the end of the mainnet checkpoint data in chainparams.cpp, that is where checkpoint data ends
   - Find the highest block height of checkpoint data, let's call it HEIGHT
   - Run `./util/checkpoints.pl 1000 HEIGHT &> checkpoints.txt` to generate the latest checkpoint data
   - To copy the new data from checkpoints.txt into the file, one way in Vim is to type ":r checkpoints.txt" which will read in a file and paste it as the current cursor
   - You will see 3 lines of "stats" at the end of the output, you just pasted in the newest stats. Delete the old stats that should be the 3 lines under the current stats
   - Make sure the new code compiles, commit and push
   - Run `./util/checkpoints.pl help` to see some basic help
     - By default it will generate checkpoints for every 1000 blocks, the "stride"
     - You can get a different "stride" by passing it in as the first arg to the script
     - To get checkpoint data for every 5000 blocks: `./util/checkpoints.pl 5000 &> checkpoints.txt`
   - checkpoints.pl will just generate the data you need, it must be manually copied into the correct place
   - Checkpoints are a list of block heights and block hashes that tell a full node the correct block history of the blockchain
   - Checkpoints make block verification a bit faster, because nodes can say "is this block a descendant of a checkpoint block?" instead of doing full consensus checks, which take more time
   - Checkpoints also provide a bit of security against some attacks that would create malicious chainforks
     - They only provide limited security, because they talk about the past, not future block heights.
   - Try to generate checkpoints as close to the release as possible, so you can have a recent block height be protected.
     - For instance, don't update checkpoints and then do a release a month later. You can always update checkpoint data again or multiple times
 - Update doc/relnotes/README.md
   - To get the stats of file changes: `git diff --stat master...dev`
 - Do a fresh clone and fresh sync with new checkpoints
 - Stop node, wait 20 minutes, and then do a partial sync with new checkpoints
 - Merge dev into master: `git checkout dev && git pull && git checkout master && git pull && git merge --no-ff dev && git push`
   - The above command makes sure that your local dev branch is up to date before doing anything
   - The above command will not merge if "git pull" creates a merge conflict
   - The above command will not push if there is a problem with merging dev
 - Make Gitea release with git tag from the master branch (make sure to merge dev in first)
   - Make sure git tag starts with a `v` such as `v1.0.3`
   - **The tag MUST be annotated** (`git tag -a v1.3.0 -m 'DragonX v1.3.0'`), not lightweight. `util/genbuild.sh` calls `git describe` *without* `--tags`, which only ever sees annotated tags — a lightweight tag makes the build stamp itself `v<older-tag>-<sha>` instead of the release version. v1.0.0 through v1.0.3 are lightweight, which is why their builds are labelled that way.
   - Verify before building: `git describe` must print exactly the tag, with no `-<n>-g<sha>` suffix.
 - Use `./build.sh` (container-based, see doc/build-containers.md) or util/gen-linux-binary-release.sh to make a Linux release binary
 - **Sign every archive and publish the signatures.** This step is mandatory and was missing from this document until v1.3.0 — its absence is why v1.1.0 and v1.2.0 were tagged but never became installable releases.
   - The wallet's in-app daemon updater pins an ed25519 public key in `ObsidianDragon/src/util/daemon_updater.h` and sets `kDaemonRequireSignature = true`. **An update is refused outright unless a valid `<archive>.sig` is published beside the archive.** No signature means every existing user silently stays on their old daemon.
   - Sign with `ObsidianDragon/scripts/sign-daemon-release.sh`:
     - `scripts/sign-daemon-release.sh sign <secret.key> <archive>...` produces `<archive>.sig` (base64 of a detached 64-byte ed25519 signature over the exact archive bytes)
     - or `scripts/sign-daemon-release.sh release <secret.key> <version>` to zip, sign, and print the checksum table in one step
   - Keep the secret key offline, mode 600. The matching base64 public key must already be pinned in `kDaemonSignaturePublicKeyBase64`.
 - Upload each Linux binary archive **and its `.sig`** to the Gitea release
 - **Paste the SHA-256 checksum table into the release body** as markdown rows of the form `| <archive>.zip | `<sha256hex>` |`. The updater parses this table and will not install an archive that is absent from it.
 - Confirm the release is actually consumable before announcing it: the updater looks for an asset whose name contains `"-" + platformToken + ".zip"` (`linux-amd64`, `macos`, `win64`). An archive named for a distro variant instead of the platform token is invisible to it.
 - Create an x86 Debian package for the release:
   - Edit contrib/debian/changelog to add information about the new release
   - Use `util/build-debian-package.sh` to make an x86 Debian package for the release
   - Debian packages should be done after you make manpages, because those are included in Debian packages
   - `lintian` is an optional dependency, it's not needed to build the .deb
   - Upload .deb to Gitea release
   - Add SHA256 checksum of .deb to release
 - ARM Debian package: `util/build-debian-package-ARM.sh` is referenced here historically but **is not present in the tree**. Skip, or restore the script first.
 - Upload the debian packages to the Gitea release page, with SHA256 sums

## Platform-specific notes

- Use `./util/build-mac.sh` to compile on Apple/Mac systems
- Use `./util/build-win.sh` to build on Windows

## Optional things

### Updating RandomX

If you need to update the source code of our in tree copy of RandomX, open an issue in the [DragonX Git repository](https://git.dragonx.is/DragonX/dragonx/issues) to track the details. Currently we use RandomX v1.2.1 from the official repo at https://github.com/tevador/RandomX/releases/tag/v1.2.1
