Tutorial · Regtest

A Chain You Can Rebuild

Tests are only useful if they start from the same place every time. This page gives you a script that builds a known regtest chain in about five seconds, explains what is and is not the same between two runs, and shows how to freeze a chain so it comes back byte for byte.

About 15 minutes · Checked 2026-10-21
Before you start

You need Divi 3.0.0 installed as in start your first regtest node. The script below makes its own data folder and its own ports, so it can run next to the node in ~/divi-regtest without touching it. Blocks are made by the C++ node with setgenerate; IronDivi cannot make regtest blocks, but it can follow a chain built this way, as shown in two regtest nodes.

1Two kinds of "the same"

A regtest chain can be "the same" in two different ways, and it pays to know which one your test needs.

Same shapeSame bytes
How you get itRun the same script on an empty folderCopy a stopped node's folder and start the copy
Heights, balances, amounts, confirmationsIdenticalIdentical
Genesis blockIdenticalIdentical
Addresses, transaction ids, block hashesNew every runIdentical
Good forTests that check amounts and statesTests that compare hashes, fixtures shared between machines, bug reports

Why do hashes change? Every fresh wallet makes new random keys, so every reward goes to a different address, and every block records the time it was made. The node has no switch to fix either one: its generateblock command can add chosen transactions to a block but cannot set the block's time. So a script gives you the same shape, and a snapshot gives you the same bytes.

2The script

Download make-chain.sh and make it executable. It takes three arguments: a data folder and two ports. It writes a regtest divi.conf with a fresh random RPC password, starts the node, makes 101 blocks, sends 500 DIVI to an address called Alice and 250 to one called Bob, and confirms both.

curl -O https://services.divi.domains/tutorials/reproducible-chain/make-chain.sh
chmod +x make-chain.sh
./make-chain.sh ~/regtest-fixture 51496 51497

The parts worth reading before you run it:

Change the middle of the script to build the chain your test needs: more addresses, a vault (see vaults on regtest), payments at exact heights (see give yourself coins on regtest). Keep the shape of it: make blocks, act, make blocks.

3Run it twice and compare

Two runs, two folders, two sets of ports, one after the other:

./make-chain.sh ~/regtest-fixture 51496 51497
height    107
balance   99999.99995480
alice     500.00000000 in 915b92eeba6a21f9e616d8f84b52fd15f6878bf01f09f58f56ca0bdc3ece9841 ("confirmations":6)
bob       250.00000000 in cd4ddcce07ac1bcd356aff93589838c90ec806c95762bd17ca4ad7aaa6c25fa4 ("confirmations":5)
tip hash  9d105aa50f23c71bc4061b3743783dec650c1ae442d25d56a6890dccc90308c3
genesis   0000000b3f9980dcf71f5f52d69e30d3b02f807e0a77b91b6091701e4ae51a6f
./make-chain.sh ~/regtest-fixture-2 51506 51507
height    107
balance   99999.99995480
alice     500.00000000 in ac6fbccd2b41d5f8fe40ef4114528e1487d1fc0ed182c48840978615f0b6b5a9 ("confirmations":6)
bob       250.00000000 in 5474c91ccdb2a99aeae79ceef1f5d9bd026c56aaac541ca0333f73ceb7551fd5 ("confirmations":5)
tip hash  140a5ec76990699fb2163ac1a6dda2584b4938e5c1806bccb00d305101220e78
genesis   0000000b3f9980dcf71f5f52d69e30d3b02f807e0a77b91b6091701e4ae51a6f

Every number matches; every hash after the genesis block differs. Each run took four to five seconds.

Two details explain the numbers. The balance is 99,999.9999548, not 99,250, because Alice and Bob are addresses in the node's own wallet, so the only money that left the wallet is the two fees. And Bob has 5 confirmations to Alice's 6 because his payment went into block 103 and hers into block 102.

blocks in the chain
107
seconds to build it
~5
hashes that match between runs
genesis only

4Freeze a chain with a snapshot

To get the same bytes, build the chain once, stop the node, and pack its regtest folder. Stop first: copying the files of a running node can catch the database half-written.

divi-cli -datadir=~/regtest-fixture stop
tar -C ~/regtest-fixture -czf ~/regtest-fixture.tgz regtest
ls -l ~/regtest-fixture.tgz
… 496457 … regtest-fixture.tgz

The 107-block chain packs to under half a megabyte (19 MB unpacked, mostly preallocated block files).

Pack regtest, not divi.conf

The snapshot holds the chain and the wallet, which is what you want. Leave divi.conf out: it holds the RPC password, and a snapshot often ends up in a git repository or a shared folder. Each machine that uses the snapshot writes its own divi.conf with its own password and ports, as the script does. The wallet inside is a regtest wallet, worth nothing anywhere else, so sharing it is fine.

5Play, then reset

Unpack the snapshot into any folder that has a regtest divi.conf and start a node on it. It comes back at the same height with the same tip hash, and the same transaction is still there with the same confirmations:

divid -datadir=~/regtest-play -daemon
divi-cli -datadir=~/regtest-play getbestblockhash
9d105aa50f23c71bc4061b3743783dec650c1ae442d25d56a6890dccc90308c3
divi-cli -datadir=~/regtest-play getbalance
99999.99995480
divi-cli -datadir=~/regtest-play gettransaction 915b92eeba6a21f9e616d8f84b52fd15f6878bf01f09f58f56ca0bdc3ece9841
… "confirmations" : 6, …

Now do whatever your test does. Here, a payment and three blocks:

divi-cli -datadir=~/regtest-play sendtoaddress $(divi-cli -datadir=~/regtest-play getnewaddress) 42
divi-cli -datadir=~/regtest-play setgenerate 3
divi-cli -datadir=~/regtest-play getblockcount
110

To go back, stop the node, replace the regtest folder with the snapshot, and start again. The three blocks and the payment are gone:

divi-cli -datadir=~/regtest-play stop
rm -rf ~/regtest-play/regtest
tar -C ~/regtest-play -xzf ~/regtest-fixture.tgz regtest
divid -datadir=~/regtest-play -daemon
divi-cli -datadir=~/regtest-play getblockcount
107
divi-cli -datadir=~/regtest-play getbestblockhash
9d105aa50f23c71bc4061b3743783dec650c1ae442d25d56a6890dccc90308c3

The rm -rf line deletes the chain in that folder. Check the path before you press Enter, and never point it at a folder you have not restored from a snapshot.

6Share the chain with a second node

A second node does not need the snapshot. Give it an empty folder, a divi.conf with connect= pointing at the restored node, and it downloads the whole chain in a few seconds:

divid -datadir=~/regtest-second -daemon     # its divi.conf has connect=127.0.0.1:51496
divi-cli -datadir=~/regtest-second getblockcount
107
divi-cli -datadir=~/regtest-second getbestblockhash
9d105aa50f23c71bc4061b3743783dec650c1ae442d25d56a6890dccc90308c3

The second node has its own new wallet, so it sees the same chain but none of the coins. That is the usual setup for testing a payment between two parties: send to an address from the second node's getnewaddress. The full two-node setup, including an IronDivi follower, is in two regtest nodes.

7Use it in a test run

Which to use depends on the test:

Either way, each test run follows the same four steps: build or restore, start and wait until getblockcount answers, run the tests, stop the node. The waiting loop in the script is the one to copy: it gives up if divid exits rather than spinning forever. How to talk to the node from Python or JavaScript is in test your app on regtest.

If something goes wrong

SymptomCauseFix
divid exited: see …/debug.log (port … already in use?)Another node or program holds one of the two portsPick two other ports. On Linux, ss -ltn lists the ports in use.
refusing to delete …: it is not empty and has no regtest divi.confThe folder you named holds something elseName a new or empty folder. The guard is doing its job.
Restored node starts at height 0The snapshot was unpacked one level too deep, so there is no regtest folder directly inside the data folderList the data folder: it should contain divi.conf and regtest.
Restored node's tip hash differs from the snapshot'sThe snapshot was taken while the node was running, or the node made blocks after the restoreStop the node before packing; restore again.
Your test asserts a transaction id and fails on every new runIds change between script runsAssert amounts and confirmations, or switch to a snapshot.

Still stuck? Ask the Divi chatbot, or see all tutorials.