Tutorial · Regtest

Two Regtest Nodes on One Computer

Run C++ Divi and IronDivi side by side on your own private chain: the C++ node makes the blocks, the IronDivi node follows it, and you watch blocks and payments travel between the two.

About 12 minutes · Checked 2026-10-21

1Why two nodes

A single regtest node (the previous tutorial) proves that your commands work. Two nodes prove that what one node does is accepted by another: the block you made really is a valid block, and the payment you sent really does travel over the network. That is the test that matters before you trust code on testnet or mainnet.

Using one of each kind is deliberate. C++ Divi (the original node, version 3.0.0) is the only one that can make regtest blocks. IronDivi (the Rust node) cannot make them yet, but it can connect, download the chain, check every block, keep a wallet and send payments. So the C++ node is the block maker and IronDivi is the follower, which is exactly the role a second node plays on the real network.

2What you need

If you finished the previous tutorial you already have node A and can skip to step 5.

3Ports: who listens where

Each node needs two ports: one where other nodes connect to it (the peer port) and one where its command tool connects (the RPC port). Two nodes on one computer cannot share them, so node A keeps the regtest defaults and node B gets its own.

Node A: C++ DiviNode B: IronDivi
RoleMakes blocks, keeps a walletFollows A, keeps a wallet
Data folder~/divi-regtest (chain in regtest/ inside it)~/iron-regtest (chain directly inside it)
Peer port51476 (default)none needed: B only dials out, to A
RPC port51475 (default)51485 (chosen here)
How it finds the otherWaits; B connects to it--connect 127.0.0.1:51476
Regtest never looks for peers on its own

Mainnet and testnet nodes find each other through seed addresses built into the software. Regtest has none, so two regtest nodes stay strangers until you point one at the other. --connect on IronDivi does that and also turns off listening and the seed lookup: in its log you will see connect-only: peers=["127.0.0.1:51476"], dns seeds off, listen=false.

4Start node A (C++ Divi)

The settings file is the one from the previous tutorial with one more line, listen=1, so node A accepts a connection from B. bind=127.0.0.1 keeps that door open only to programs on this computer.

mkdir -p ~/divi-regtest
cat > ~/divi-regtest/divi.conf <<'EOF'
regtest=1
server=1
listen=1
bind=127.0.0.1
rpcuser=regtest
rpcpassword=choose-a-long-random-password
staking=0
EOF

divid -datadir=~/divi-regtest -daemon
DIVI server starting

# a few seconds later: a chain of 101 blocks with 100,000 DIVI to spend
divi-cli -datadir=~/divi-regtest setgenerate 101 > /dev/null
divi-cli -datadir=~/divi-regtest getblockcount
101

If node A already has blocks from before, skip the setgenerate: node B will download whatever A has.

5Start node B (IronDivi) and watch it catch up

IronDivi takes its settings on the command line. Give it its own folder and RPC port, tell it to connect only to A, and turn staking off so it stays a quiet follower:

mkdir -p ~/iron-regtest
irondivid --regtest --datadir ~/iron-regtest --rpcport 51485 \
          --connect 127.0.0.1:51476 --staking=false &

IronDivi's log goes to debug.log inside its data folder. Within a couple of seconds it shows the handshake with A and the whole chain arriving:

grep -E "Handshake|Starting sync|sync complete" ~/iron-regtest/debug.log
INFO divi_network::connection: Handshake complete with 127.0.0.1:53940 (DIVI Core: 3.0.0.0), height 101
INFO divi_network::sync: Starting sync from height 0 to 101
INFO divi_network::sync: Block sync complete at height 101
INFO divi_network::sync: Exiting IBD mode — full validation enabled for new blocks

Now ask both nodes where they are. Note that irondivi-cli needs --regtest, the data folder and the RPC port each time (the data folder is where it finds its login, see below), just as divi-cli needs -datadir:

irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 getblockchaininfo
{
  "bestblockhash": "c98ddf4a71857ee104c7a0a50e0934299b732614033902fd5d88826f108d266f",
  "blocks": 101,
  "chain": "regtest",
  "headers": 101,
  "verificationprogress": 1.0,
  ...
}

divi-cli -datadir=~/divi-regtest getbestblockhash
c98ddf4a71857ee104c7a0a50e0934299b732614033902fd5d88826f108d266f

Same height, same best block hash: B has downloaded and checked every block A made, and agrees with it. Each side also lists the other as a peer:

irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 getpeerinfo
[ { "addr": "127.0.0.1:53940", "inbound": false, "subver": "DIVI Core: 3.0.0.0", ... } ]

divi-cli -datadir=~/divi-regtest getpeerinfo
[ { "subver" : "/IronDivi:0.1.0/", "inbound" : true, ... } ]
Reading the numbers

The output on this page was captured with IronDivi 0.2.6 on a shared test machine where A ran on ports 53940/53941 and B on RPC port 53942. With the defaults above you will see 51476 in B's log and peer list where ours shows 53940, and your own block hashes and addresses. IronDivi 0.2.6 still announces itself to peers as /IronDivi:0.1.0/; that is a label in the handshake, not the version you installed.

IronDivi makes its own login

Started as above, with no --rpcuser or --rpcpassword, IronDivi 0.2.6 writes a random login into a file called .cookie in its data folder (its log says RPC cookie authentication) and deletes the file when it stops. irondivi-cli reads that file, which is why it needs --datadir ~/iron-regtest. Leave the folder off and you get HTTP 401 Unauthorized. IronDivi 0.2.5 had no login at all in this setup; if you are still on 0.2.5, upgrade, or set rpcuser and rpcpassword in an irondivi.conf in the data folder.

6Make blocks on A, see them on B

divi-cli -datadir=~/divi-regtest setgenerate 5 > /dev/null

divi-cli -datadir=~/divi-regtest getblockcount
106
irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 getblockcount
106
irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 getbestblockhash
93444e7f12570b614f2a8f8067ec14f183bf57e54dfa22254d92f2b09f301625

grep "sync complete" ~/iron-regtest/debug.log | tail -1
INFO divi_network::sync: Block sync complete at height 106

A made five blocks; within a few seconds B had them. Try it the other way round and you get the limit of today's IronDivi:

irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 setgenerate 1
error code: -1: setgenerate is not yet implemented - requires full mining subsystem

7Pay from A to B, and back

B has its own wallet, empty so far. Make an address there, pay it from A, and watch the payment appear on B first as unconfirmed, then confirmed once A makes a block:

irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 getnewaddress
xxVCFGfzeqiHYV9cRRPhVnJJgv6DtZnQJm

divi-cli -datadir=~/divi-regtest sendtoaddress xxVCFGfzeqiHYV9cRRPhVnJJgv6DtZnQJm 500
72fbb78f91a90c8cfe94afd9f8a1e53427edb6bce21355189801fcbf1e544ee7

# on B, a moment later: in the mempool, not yet spendable
irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 getrawmempool
[ "72fbb78f91a90c8cfe94afd9f8a1e53427edb6bce21355189801fcbf1e544ee7" ]
irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 getwalletinfo
{ "balance": 0.0, "unconfirmed_balance": 500.0, "txcount": 1, ... }

# A confirms it
divi-cli -datadir=~/divi-regtest setgenerate 1 > /dev/null
irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 getbalance
500.0

Now the other direction. B spends from its wallet; A sees the payment, puts it in a block, and B's balance drops by 100 plus a fee:

divi-cli -datadir=~/divi-regtest getnewaddress
xx69tbbZYMwEwKS1wdHZc2WkReEQS1JWFN
irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 sendtoaddress xx69tbbZYMwEwKS1wdHZc2WkReEQS1JWFN 100
0f7352a2279ed5206839198356a1cb6a0fce7582b333ba0d220e6aeef243e72d

divi-cli -datadir=~/divi-regtest getrawmempool
[ "0f7352a2279ed5206839198356a1cb6a0fce7582b333ba0d220e6aeef243e72d" ]
divi-cli -datadir=~/divi-regtest setgenerate 1 > /dev/null
divi-cli -datadir=~/divi-regtest gettransaction 0f7352a2279ed5206839198356a1cb6a0fce7582b333ba0d220e6aeef243e72d
{ "amount" : 100.00000000, "confirmations" : 1, ... }
irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 getbalance
399.99997

That round trip is the whole point: a transaction built and signed by one implementation was relayed, accepted and confirmed by the other. Everything you can do on one node, you can now check on the other.

8Stop both

# node A
divi-cli -datadir=~/divi-regtest stop
DIVI server stopping

# node B
irondivi-cli --regtest --datadir ~/iron-regtest --rpcport 51485 stop
Divi server stopping
tail -1 ~/iron-regtest/debug.log
INFO irondivid: IronDivi shutdown complete

Both chains stay on disk. Start A, then B, in the same way next time and B will pick up wherever A has got to. To reset, stop both, delete ~/divi-regtest/regtest and ~/iron-regtest, and start again: B must be reset whenever A is, because a fresh A makes a different chain.

If something goes wrong

You seeWhat it meansDo this
B's log keeps saying Connecting to peer 127.0.0.1:51476 and never Handshake completeNothing is listening on A's peer port.Check A is running and its divi.conf has listen=1; if you changed A's port=, use the same number after --connect.
B's getblockcount stays behind AB lost the connection, or A's blocks have not reached it yet.Wait a few seconds; B reconnects on its own (Reconnecting to static peer in the log). If it never catches up, look at the last lines of ~/iron-regtest/debug.log.
irondivi-cli: connection refusedWrong RPC port, or B has not finished starting.Use the same --rpcport you gave irondivid, and include --regtest.
B started but getblockchaininfo says "chain": "main"--regtest was left off.Stop B, delete its folder and start it again with --regtest.
irondivi-cli: HTTP 401 UnauthorizedThe tool could not find B's login file, .cookie.Add --datadir ~/iron-regtest (the folder you gave irondivid) to every irondivi-cli line.
irondivi-cli ... stop says Divi server stopping but the process staysYou are running IronDivi 0.2.5, whose stop command does nothing. 0.2.6 stops.Upgrade, or send the stop signal: pkill -TERM -f "irondivid --regtest"; the log ends with IronDivi shutdown complete.
Payment from B never confirmsOnly A makes blocks.Run setgenerate 1 on A.
Address already in use when starting BAnother program has port 51485 (or whatever you chose).Pick a different --rpcport and use it in every irondivi-cli call.

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