Skip to content

Writing tests against it

The local network is shared and it keeps growing. Every test we run adds to the same chain, and the autominer adds a block whenever it likes. A test that assumes it has the chain to itself works the first time and fails the tenth. These are the habits that keep our tests honest.

  • Wait for a status, or anything after it. Never wait for one exact status. A block can be mined between two polls, so a test waiting for SEEN_ON_NETWORK must also accept MINED.
  • Mine explicitly. Don’t wait on the autominer, which takes 10 minutes. For runs that must not see a block they didn’t ask for, set MINE_INTERVAL=0 in .env and run ./scripts/start.sh again.
  • Don’t assume heights. Read the tip from the DataHub, and remember that the subsidy halves every 150 blocks.
  • Use a fresh callback token per run. An X-CallbackToken that is new for each run scopes the SSE stream and the webhooks to that run’s Transactions.
  • Fund through Arcade when the test needs a proof. That is faucet.sh send … --arcade, as in Getting coins.
  • Check the health first. curl -sf http://127.0.0.1:23012/health checks Arcade, and ./scripts/status.sh also tells us whether Merkle Service is connected. Without that connection nothing gets past ACCEPTED_BY_NETWORK, and the test fails for a reason that has nothing to do with our code.
  • A wiped chain needs no other clean-up. After reset.sh and start.sh, the faucet rescans from scratch and Arcade’s store is wiped with the rest.

The libtokensv *_localnet_test.dart files are a working example of all of this. They broadcast and mine every kind of Lineage Token on this network, and are skipped when the network isn’t running.

Before Teranode, our local setup was an SV Node in regtest mode, at first on its own and later behind ARC in arc_regtest. The two can run side by side with localnet-teranode, as they share no ports, containers or volumes. Moving a client across is mostly a change of addresses:

SV Node and arc_regtest localnet-teranode
ARC at http://localhost:9090/v1 Arcade at http://127.0.0.1:23011, with no /v1
SV Node P2P on localhost:18333 Teranode’s wire protocol on 127.0.0.1:18444, with a user agent containing BSV
SV Node RPC on localhost:18332 Teranode’s RPC on 127.0.0.1:19292, with no wallet methods
bitcoin-cli sendtoaddress, or fund.sh <address> faucet.sh send <address> <satoshis> --arcade
bitcoin-cli generate 101 mine.sh 101, although start.sh already does this
ZeroMQ on localhost:28332 none: Arcade’s SSE stream and webhooks for our Transactions, or libp2p gossip for blocks
Chronicle at height 15,000 Chronicle at height 200

The client code needs a few changes too:

  1. POST /tx answers 202 RECEIVED straight away, and there is no X-WaitFor. The client follows the status afterwards.
  2. Transactions must be in Extended Format.
  3. There are new statuses (SEEN_MULTIPLE_NODES and PENDING_RETRY), and a reorg moves a MINED Transaction back to SEEN_ON_NETWORK.
  4. POST /txs takes the Transactions concatenated as application/octet-stream, not as a JSON array.

libspiffy 4.6.0 and later handle all of this. The repository’s CONSUMING.md has the full comparison.