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
- C++ Divi 3.0.0, as in install the Divi node.
- IronDivi 0.2.5 or later, as in install IronDivi. That page unpacks it into a folder such as
~/irondivi/irondivi-x86_64-linux-musl/; the commands below assume that folder is on yourPATH, otherwise put the folder in front ofirondividandirondivi-cli. - Two terminals, one per node, or one terminal and some patience.
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++ Divi | Node B: IronDivi | |
|---|---|---|
| Role | Makes blocks, keeps a wallet | Follows A, keeps a wallet |
| Data folder | ~/divi-regtest (chain in regtest/ inside it) | ~/iron-regtest (chain directly inside it) |
| Peer port | 51476 (default) | none needed: B only dials out, to A |
| RPC port | 51475 (default) | 51485 (chosen here) |
| How it finds the other | Waits; B connects to it | --connect 127.0.0.1:51476 |
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:51476 (DIVI Core: 3.0.0.0), height 102
INFO divi_network::sync: Starting sync from height 0 to 102
INFO divi_network::sync: Block sync complete at height 102
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 and the RPC port each time, just as divi-cli needs -datadir:
irondivi-cli --regtest --rpcport 51485 getblockchaininfo { "bestblockhash": "163c205553891647aad42619e4069d1dd1356a4d62556f5227e9e4ca4bb8ccb7", "blocks": 102, "chain": "regtest", "headers": 102, "verificationprogress": 1.0, ... } divi-cli -datadir=~/divi-regtest getbestblockhash 163c205553891647aad42619e4069d1dd1356a4d62556f5227e9e4ca4bb8ccb7
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 --rpcport 51485 getpeerinfo [ { "addr": "127.0.0.1:51476", "subver": "/Divi Core:3.0.0/", "inbound": false, ... } ] divi-cli -datadir=~/divi-regtest getpeerinfo [ { "subver" : "/IronDivi:0.1.0/", "inbound" : true, ... } ]
The output on this page was captured on a shared test machine where A ran on ports 53830/53831 and B on 53840/53841, and A already had 102 blocks. With the defaults above you will see 51476 in B's log and peer list, and your own block hashes. IronDivi 0.2.5 announces itself to peers as /IronDivi:0.1.0/; that is a label in the handshake, not the version you installed.
Started as above, IronDivi's RPC port answers anyone on this computer with no name or password. That is fine for a throwaway regtest node on a laptop. On a shared machine, or for anything beyond regtest, add --rpcuser and --rpcpassword (both are needed) and give the same two to irondivi-cli.
6Make blocks on A, see them on B
divi-cli -datadir=~/divi-regtest setgenerate 5 > /dev/null divi-cli -datadir=~/divi-regtest getblockcount 107 irondivi-cli --regtest --rpcport 51485 getblockcount 107 irondivi-cli --regtest --rpcport 51485 getbestblockhash 99c2b4d463d83a5c122d0601290560c2ba5befd682919a9938a07ac29a045285 grep "sync complete" ~/iron-regtest/debug.log | tail -1 INFO divi_network::sync: Block sync complete at height 107
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 --rpcport 51485 setgenerate 1
error code: -32603: 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 --rpcport 51485 getnewaddress yGGM6RD2V39njpw9JPtU2PY8USZ9JnYDTt divi-cli -datadir=~/divi-regtest sendtoaddress yGGM6RD2V39njpw9JPtU2PY8USZ9JnYDTt 500 e2fd4a9d82044f20ad446d8ec796d5eddd4719cf91717c09febced32c06b209f # on B, a moment later: in the mempool, not yet spendable irondivi-cli --regtest --rpcport 51485 getrawmempool [ "e2fd4a9d82044f20ad446d8ec796d5eddd4719cf91717c09febced32c06b209f" ] irondivi-cli --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 --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 yLm... (an address on A) irondivi-cli --regtest --rpcport 51485 sendtoaddress yLm... 100 37d5641def604918307bdee27f988f088ca6e0ff31bf3c42b717031a7e1c6e8c divi-cli -datadir=~/divi-regtest getrawmempool [ "37d5641def604918307bdee27f988f088ca6e0ff31bf3c42b717031a7e1c6e8c" ] divi-cli -datadir=~/divi-regtest setgenerate 1 > /dev/null divi-cli -datadir=~/divi-regtest gettransaction 37d5641def604918307bdee27f988f088ca6e0ff31bf3c42b717031a7e1c6e8c { "amount" : 100.00000000, "confirmations" : 1, ... } irondivi-cli --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: in IronDivi 0.2.5 the stop command only answers, it does not stop the node. # Send it a termination signal instead; it flushes and exits cleanly. pkill -TERM -f "irondivid --regtest" 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 see | What it means | Do this |
|---|---|---|
B's log keeps saying Connecting to peer 127.0.0.1:51476 and never Handshake complete | Nothing 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 A | B 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 refused | Wrong 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 ... stop says Divi server stopping but the process stays | Known gap in IronDivi 0.2.5: the stop command does nothing. | pkill -TERM -f "irondivid --regtest"; the log ends with IronDivi shutdown complete. |
| Payment from B never confirms | Only A makes blocks. | Run setgenerate 1 on A. |
| Address already in use when starting B | Another 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.