Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

localnet-teranode

A local BSV regtest network built on Teranode, for developing and testing wallets, services and apps on your own machine.

One command brings up a single regtest Teranode in Docker, with an ARC-compatible broadcast API, merkle proofs, a block every ten minutes and a faucet to fund your test addresses.

It replaces arc_regtest (SV Node + ARC), and the two can run side by side: they share no ports, containers, networks or volumes.

What's inside

Component Version Role
Teranode v0.16.0 The regtest node
Arcade v0.16.0 ARC-compatible API: broadcast transactions, follow their status, fetch merkle proofs
Merkle Service v0.6.2 Watches the node's gossip and gives Arcade the data for its merkle proofs
Autominer Mines a block every 10 minutes (configurable)
Faucet A small Go tool that holds the mined coins and sends them to your addresses

Requirements

  • Docker, with about 4 GB of memory free (the stack uses about 2.5 GB when idle)
  • Go 1.27, for the faucet

Getting started

./scripts/start.sh

The first run writes .env with fresh secrets, starts the containers, switches Teranode on, creates the faucet key, mines to height 101 so the faucet has spendable coins, and waits for Arcade to be ready. It is safe to run again at any time.

Then:

./scripts/status.sh                              # containers, chain tip, faucet balance
./scripts/faucet.sh send <address> <satoshis>    # fund a test address
./scripts/mine.sh 1                              # mine a block now instead of waiting

When you are done, ./scripts/stop.sh stops the stack and keeps the chain; ./scripts/reset.sh wipes the chain and starts over from nothing.

Connecting your app

Point your ARC client at Arcade on http://127.0.0.1:23011. Note that there is no /v1 prefix: Arcade serves the ARC API at its root.

  • POST /tx submits a transaction (Extended Format)
  • GET /tx/{txid} returns its status, plus the merklePath once it is mined
  • GET /policy returns the fee policy

Arcade answers a submission with 202 RECEIVED straight away and broadcasts afterwards. The status then moves through ACCEPTED_BY_NETWORK and SEEN_ON_NETWORK to MINED after the next block. libspiffy 4.6.0 follows these steps for you.

Testing from a phone on your LAN? Set HOST_IP=0.0.0.0 in .env and run ./scripts/start.sh again. Arcade (23011), the DataHub (18090) and the wire-protocol port (18444) then listen on every interface; use your computer's LAN address in the app.

For the full guide (every endpoint, getting coins, following a transaction to its proof, and writing reliable tests) see CONSUMING.md.

Ports

Everything listens on 127.0.0.1. Arcade, the DataHub and the wire-protocol port follow HOST_IP instead.

Port Service What it's for
23011 Arcade ARC-compatible API (no /v1); health check on 23012
18090 DataHub http://127.0.0.1:18090/api/v1 for blocks, headers, transactions and UTXO status; a block explorer UI at /
19292 RPC generate, generatetoaddress, getblockchaininfo, sendrawtransaction (try ./scripts/rpc.sh <method> [params])
18084 Propagation Teranode's own POST /tx and POST /txs
18444 Wire protocol Bitcoin P2P (see the user agent note below)
19905 libp2p Gossip topics teranode/bitcoin/1.0.0/regtest-{block,subtree,node_status,rejected-tx}
28080 Merkle Service /watch and /reprocess, used by Arcade; you rarely need it
25432 / 29092 / 23000 Postgres / Redpanda / Aerospike Teranode's data stores

Scripts

All scripts live in scripts/.

Script What it does
start.sh Starts everything and makes it ready to use
status.sh Shows containers, node state, chain tip and faucet balance
mine.sh [count] [address] Mines blocks now, paying the faucet unless you give an address
faucet.sh init | address | balance | send <addr> <sats> [--arcade] Runs the faucet; --arcade broadcasts through Arcade instead of the node's RPC
rpc.sh <method> [params...] Sends a raw JSON-RPC call
verify-proof.py <txid> Checks Arcade's merklePath for a mined transaction against the block header
stop.sh Stops the stack and keeps the chain
reset.sh Stops the stack and wipes the chain (keeps the faucet key and .env)
setup.sh Writes .env with fresh secrets (start.sh runs it for you when .env is missing)

Good to know

These are the things most likely to surprise you, especially coming from arc_regtest.

There is no node wallet. Teranode does not offer sendtoaddress or getnewaddress, so the faucet (faucet/main.go) does that job. It keeps its key in faucet/key.wif, and the autominer and mine.sh pay their block rewards to it (miner.env). The faucet finds those coins through the DataHub, waits the 100 blocks a block reward needs before it can be spent, and signs and broadcasts its own transactions. It tracks its coins in faucet/state.json.

Wire-protocol clients must identify as BSV. The node only accepts a P2P peer whose user agent contains BSV or Bitcoin SV (case-sensitive), and bans any other peer for 24 hours. spiffynode's default /bsv-p2p-dart:0.1.0/ and libspiffy's /LibSpiffy:1.0/ do not pass. The ban is per IP, and every connection from your machine arrives from the same Docker gateway address, so one misconfigured client locks out the whole host. To lift it, run docker restart tnl-legacy (rpc.sh clearbanned does not reach this service).

Fork heights are different. Genesis activates at height 100 and Chronicle at 200. arc_regtest's SV Node activates them at 1 and 15,000.

Arcade charges a fee even though the node doesn't. Teranode here accepts zero-fee transactions, but Arcade enforces its default of 100 sat/kB (see GET /policy).

Some RPC methods are missing. getblockcount and gettxout are listed but not implemented. Use getblockchaininfo (which can lag a new block by a few seconds), or the DataHub's /bestblockheader/json and /utxos/<txid>/json.

A fresh node starts idle. Teranode starts in the IDLE state and mines nothing until it is switched to RUNNING. start.sh does this for you.

How the merkle proofs are made

Merkle Service follows Teranode's libp2p gossip (subtrees and blocks) for the transactions Arcade registers with it, and calls Arcade back with partial proofs. Arcade then builds the full proof (a BUMP) using block data from the DataHub. Merkle Service stores its data in a merkle database on the same Postgres.

To connect, Merkle Service dials Teranode's peer service using a peer ID pinned in .env (p2p_private_key, TERANODE_PEER_ID; setup.sh generates them with tools/p2pkey). Teranode accepts the connection because p2p_allow_private_ips=true is set, since the Docker network is private. The DataHub's rate limit for heavy routes is also turned off (asset_httpHeavyRateLimit=0), as this stack's own tools are its only readers.

What has been tested

Starting from reset.sh and start.sh, a faucet payment submitted through Arcade went from RECEIVED to ACCEPTED_BY_NETWORK in about 2 seconds, to SEEN_ON_NETWORK about 8 seconds later, and to MINED about 3 seconds after the next block. Its merklePath computes the merkle root in the block header.

So far every block has held a single subtree. A block with several subtrees (thousands of transactions) has not been tried yet.

Credits

The Docker Compose setup is adapted from teranode-quickstart (Apache-2.0, see config/QUICKSTART_LICENSE), cut down to a single regtest node.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages