skip to Main Content

Integration testing with NBitcoin

In Programming the Blockchain in C#, we learned about how to develop with Bitcoin using a public block explorer like QBitNinja.

However using a full block explorer is very often not desirable. If you want to provide reliable service to your customers, you can’t afford downtime caused by third party services. One solution is to setup your own block explorer on your own infrastructure.

However, setting up your own full block explorer is quite challenging. A full block explorer need to index the entirety of all transactions, blocks and scriptPubKeys. This is time consuming, require a big configuration and lot’s of storage. (Blockstream’s Esplora is recommended if you want your full block explorer)

Moreover, this can be quite challenging to effectively test against it. One could imagine mocking the block explorer, but the majority of bugs, especially in Bitcoin programming happens at the integration stage.

So how can we do our integration testing?

One solution is to rely on a shared block explorer at the company level on Testnet. Testnet is an alternative public blockchain for Bitcoin but with worthless coins. Sadly, testnet is highly unpredictable because of very variable hashing power. The chain can be blocked for a day, or mine 1 block every 5 seconds. (we call this event a block storm)

Sharing a testnet server with the whole team is bound to have several issues like lack of reproductibility, bad coverage of corner cases, and penury of testnet coins.

Luckily, you can make your code easy to test in two ways:

  1. Use Regtest
  2. Use NBitcoin.TestFramework
  3. Having an architecture which do no rely on a full block explorer

First, Regtest is a private chain where the developer has the power to mine as many block he wants. Everything which can be done on Mainnet with 100% of hashing power, can be done on Regtest. This make it very useful for integration testing.

Second, NBitcoin.TestFramework is a framework which allow you, in C#, to easily create your own Regtest chain, create bitcoin nodes, connect them together or interact with them.

Third, in almost 95% of services developed for Bitcoin, a full block explorer is not actually needed. What you need is a way to track a wallet’s UTXOs. We will see how to manage a wallet through Bitcoin Core RPC wallet API.

Use case: Using Bitcoin core RPC for sending from Alice to Bob
In this example, we will test a simple test case illustrating Alice sending money to Bob.

We will use Bitcoin Core RPC wallet API to for our operations.

Bitcoin Core RPC is a JSON API exposed by the bitcoind deamon. The bitcoind deamon exposes:

  1. RPC API (we will see in this article)
  2. REST API (rarely used)
  3. Bitcoin P2P protocol (we will see in a later article)
  4. ZMQ queues for block and wallet transaction notifications (not supported by NBitcoin)

We will use .NET Core in command line. We advise you to use a proper IDE like Visual Studio Code (Linux, Mac, Windows) or Visual Studio Community (Windows only) to easily debug or step by step in the code.

Let’s create a test project with NBitcoin.TestFramework, NBitcoin and NBitcoin.Altcoins.