Simulating the Bitcoin Network

This morning, I'd like to make some progress on a demonstration of Lightning transactions supported by private Bitcoin and Lightning infrastructure deployed to Kubernetes. See my previous post for more background and an overview of where I am so far.

I have deployed a Bitcoin node using the kiln operator and connected a Lightning node to it, however, I am running the Bitcoin node in simnet mode, meaning it is simulating its own isolated Bitcoin network. This requires some explanation...

Providing the implementation of the Bitcoin node is an image that runs btcd which is a Bitcoin node written in Go. This particular Bitcoin node implementation supports this concept of simnet. As far as I know, other node implementations do not support same. So far, I haven't found great documentation of the btcd simnet, but I've found this gist to be a useful summary. Also, the Docker demo included in lnd offered a lot of clues to get started using the simnet mode.

So my Bitcoin and Lightning nodes seem to be connected, but the next challenge is immendiately evident. My Lightning node logs say:

2022-02-07 21:05:13.365 [INF] LTND: Waiting for chain backend to finish sync, start_height=0

And my Bitcoin node logs say:

2022-02-07 21:04:45.183 [INF] CHAN: Chain state (height 0, hash 683e86bd5c6d110d91b94b97137ba6bfe02dbbdb8e3dff722a669b5d69d77af6, totaltx 1, work 2)

This tells me that zero blocks have ever been added to the simulated network, which is a problem for several reasons if we're demonstrating Lightning transactions.

  1. We need at least one wallet with some Bitcoin to start
  2. We need Segwit activated*
  3. We need to open a least one channel which is an on-chain transaction

*Segwit is the name of a Bitcoin soft-fork upgrade released in 2017 to protect against transaction malleability. The Lightning protocol is built around Bitcoin's post-Segwit block data organization.

So long story short, dawn your headlamps, we need to mine some blocks. Fortunately, we're in our own simulated Bitcoin network and there is absolutely zero mining competition, so this will not be computationally expensive.

From the LND Docker Demo there is a clue that activating Segwit will require generating ~400 blocks in simnet mode. So that seems like a good place to start. The technique referenced in the tutorial is a command issued from inside the Bitcoin node container.

docker exec -it btcd /start-btcctl.sh generate 400

We can certainly do something similar in a Kubernetes environment and issue this command in a pod terminal, but could this be an opportunity for the kiln operator to manage the Bitcoin node state?

I think it could be useful to specify a minimum block height in the context of simnet mode only. So, I am creating an issue to track this feature implementation. Though this will not be useful in a production environment, I need it to move forward with experimentation, and perhaps the utility of the kiln operator could be for simulations anyway. This would be the first true Bitcoin node interaction for the kiln operator, so I expect implementation will take some effort. The operator's reconciliation procedure will need to integrate with a Bitcoin node API, presumably the RPC API.

Even if we can specify a block height for the Bitcoin node to reach as quickly as it can, there is still more to the problem. We also need blocks to be continuously mined in order to support demonstrations of Lightning channel opens and closes. So I will open a second issue for the operator to support a specific block production rate even after the minumum block height is acheived. I expect this to be challenging as well, especially from an observability perspective as the operator will need to track block production over time.

I am quite sure there will be many smaller problems to solve before solving these issues. Among other things, this will require me to get much more hands-on with the Go programming language. But hey, YOLO.

comments powered by Disqus