Running a testnet node.
The fastest path from "I have a GPU or ASIC" to "shares are landing" on the testnet demo. Five steps.
01 What gccd is
GCC is the reference chain that ships with the white-label stack. It is a Proof-of-Work chain forked from Litecoin Core v0.21.5.5 and rebranded — own genesis block, own network magic, own ports, its own gcc1… address prefix. Because the fork keeps Litecoin’s internals intact, the daemon behaves exactly like a Litecoin/Bitcoin Core node: same .conf format, same JSON-RPC surface, same address and script formats. If you already know bitcoind or litecoind, you know gccd.
The chain is testnet. The units it produces are testnet units with no monetary value — the point of the chain is to give an operator a complete, running network to demonstrate, re-brand and hand on. I run GCC the same way you will: a couple of gccd containers behind Docker, an electrs indexer on top, and an Esplora-style explorer in front. This page covers the node itself — getting a single gccd up, checking it is healthy, and (for a private network) mining the first blocks yourself.
There are two daemons you will use:
gccd— the node. It validates blocks, keeps the chain state, serves the P2P and JSON-RPC ports.gcc-cli— the thin command-line client that talks togccdover JSON-RPC. Everythinggcc-cli foodoes, you can also do with a rawcurlPOST to the RPC port; the CLI is just friendlier.
The key facts to keep in mind as you go: the P2P port is 9433, the RPC port is 9332, the network magic is c7cc112a, the target block time is 60 seconds, and coinbase outputs need 100 confirmations before they can be spent.
02 Prerequisites
You need Docker and enough disk for the chain’s data directory. On a fresh testnet the data directory is small (megabytes), so any modest VPS is fine — I run the whole GCC stack on a single Contabo box.
Confirm Docker is present and that your user can talk to the daemon:
You also need a directory on the host to hold the chain data. I keep node state in a named Docker volume so it survives container rebuilds, but a bind-mounted host directory works just as well and is easier to inspect:
The gccd image is the one the build produces (in the reference stack it is tagged gcc-chain-build:v0.21.5.5). The examples below use the placeholder name gccd:latest — substitute the image tag you were given with the stack.
03 A minimal gcc.conf
gccd reads a config file from its data directory (gcc.conf). For a testnet node you want four things: RPC switched on, RPC bound to localhost only, credentials set, and the listen ports pinned to the GCC defaults. Write this to ~/gcc-node/data/gcc.conf:
A few notes on those lines:
txindex=1builds a full transaction index. electrs and the explorer expect it; without it, lookups by arbitrary txid fail.rpcbind=127.0.0.1+rpcallowip=127.0.0.1is the single most important pair on this page. It keeps the RPC listening only on the loopback interface and only accepting loopback clients. Never widen these to0.0.0.0on a public box. See section 07.rpcpassword— set a long random value. Do not commit it. For multi-service setups, the upstreamrpcauthsalted-hash scheme also works (generate it with therpcauth.pyhelper that ships with the daemon) so the plaintext password never lands in the config.addnodepoints this node at a peer. On a two-node private testnet, give each node the other’s address. Replace10.0.0.12with your peer’s internal IP. If you are running a single isolated node, omitaddnodeentirely — it will simply have no peers, which is fine forgeneratetoaddress-driven mining.
04 Run the node under Docker
With the config in place, start gccd. Mount the data directory, publish only the ports you need, and bind the RPC publish to 127.0.0.1 at the Docker layer as well as in the config — defence in depth:
Note the asymmetry in the two -p lines, and that it is deliberate:
-p 127.0.0.1:9332:9332— the RPC port is published to the host’s loopback only. Nothing off-box can reach it.-p 9433:9433— the P2P port is published on all interfaces so peers can connect. P2P is meant to be reachable; RPC is not.
Follow the log to confirm it came up:
height=0 (genesis) on a brand-new node is expected — that is the GCC genesis block. Once a peer connects (or once you mine), the tip will advance.
05 Check that it is syncing
getblockchaininfo is the health check you will run most. It tells you the chain name, the current height, the best block hash and how far through verification the node is:
If blocks is climbing and initialblockdownload is false, the node is healthy and in step with its peers. While a node is catching up, blocks lags headers and verificationprogress is below 1. The quickest one-liners for a glance:
A peer count of zero on a node that has addnode set usually means the peer is not reachable on 9433 — check the peer is listening, the internal IP is right, and no firewall is dropping the P2P port between the two boxes.
06 Mine blocks on a private testnet
On a private network there are no other miners, so you produce blocks yourself with generatetoaddress. This is the CPU-mining RPC inherited from Core — it grinds the Scrypt PoW until it finds a valid block and credits the coinbase to an address you supply. It is meant for regtest/private-testnet use, not for a contested public network.
First make an address to mine to:
Then generate some blocks to it. Here we ask for 110 blocks in one call:
Now the coinbase maturity rule bites. A coinbase output — the block reward of 50 GCC paid to the miner — cannot be spent until it has 100 confirmations on top of it. That is why this section mined 110 blocks rather than 1: it puts ten mature, spendable coinbases at the top of the chain. Check the wallet:
The immature figure is the 100 most-recent blocks’ rewards still waiting out their maturity window; trusted is what is actually spendable now. If you try to spend before block 101, you will see a Insufficient funds error even though the chain shows the coinbase — that is maturity, not a bug. (I hit exactly this on the first GCC bring-up; it is the single most common “where’s my balance” question.)
07 Keep the RPC private
This is the rule I will not let you skip. The JSON-RPC port controls the wallet and the node. Anyone who can reach it with the credentials can move funds and reorganise the operator’s view of the chain. On a public host it must never be exposed.
Concretely:
- Bind to loopback in two places.
rpcbind=127.0.0.1ingcc.confand-p 127.0.0.1:9332:9332at the Docker layer. Either alone is enough in theory; both together means a mistake in one place does not open the port. - Never
rpcallowip=0.0.0.0/0. If a second box genuinely needs RPC, put both on a private network and allow only that single peer’s address — or, better, tunnel over SSH and keeprpcallowipon loopback. - Firewall the host too. On the reference stack the host firewall DROPs the RPC/electrs ports for any source that is not the operator, so even a misconfigured bind cannot be reached from the internet.
- Rotate credentials if they are ever printed, committed, or shared. Treat a leaked
rpcpasswordas a full compromise of that node’s wallet. - P2P (9433) is the only port that should face the network, and even then only to peers you intend to gossip with.