bitcoin simulator
bitsim is the controller for the your bitcoin simulation environment. bitsim consists of:
- Bitcoin simulation node Docker image
- Node module for interacting with the simulation container
NOTE: Bitsim node is a modified version of a "regtest mode" which supports mainnet address format and mainnet magic bytes. This allows more seamless plug and play testing environment for applications.
Source code for the Bitsim Node is available here.
- docker
- nodejs
npm i --save-dev bitsim
We are going to testdrive bitsim by first booting up a bitsim docker container, and then using node.js REPL to interact with it programmatically.
docker run --name bitsim -d -p 18332-18333:18332-18333 -p 18444:18444 planaria/bitsim:0.0.2
curl https://raw.githubusercontent.com/interplanaria/bitsim/master/docker-compose.yml > docker-compose.yml && docker-compose up
NOTE: Docker-compose is required for multi peer quickstart script
node
For more information on how to use NodeJS REPL, see the docs.
NOTE: We will be using
.then
syntax to read the callbacks in realtime without async scope. it's worth noting that ordinarily, you'd probably want to use async/await.
const Bitsim = require('bitsim')
const bitsim = new Bitsim()
// mine a single block
bitsim.mine().then(r => console.log(r))
// mine 5 blocks
bitsim.mine(5).then(r => console.log(r))
// check status (most recent block header)
bitsim.last().then(r => console.log(r))
// initial fund step (more details below)
bitsim.init().then(r => console.log(r))
// add 10 "default" data transactions (more details below)
bitsim.add(10)
// add 1000 data transactions
bitsim.add(1000)
// add 100 custom data transaction
let dataOut = [ { "o0": "OP_0", "o1": "OP_RETURN", "s2": "Hello My Custom Transaction" } ]
bitsim.add(100, dataOut)
// check the mempool
bitsim.getMempoolInfo().then(r => console.log(r))
NOTE: initial funding requires mining 100 blocks to make the coinbase bitcoin eligible for spending. this coinbase transaction is used to fund a local toychain which builds and submits to the Bitsim peer.
NOTE: the term "default transaction" refers to the default prototype data out transaction provided by the Bitsim library.
// get the last block header
let lastHeight;
bitsim.getLatestHeader().then(r => console.log(r); lastHeight = r.height; )
// create a fork 3 blocks back
bitsim.fork(lastHeight - 3)
// get the new last block header
let newHeight
bitsim.getLatestHeader().then(r => console.log(r); newHeight = r.height; )
const Bitsim = require('bitsim')
const bitsim = new Bitsim()
const Bitsim = require('bitsim')
const bitsim1 = new Bitsim({ rpc: 'http://root:[email protected]:18332' })
const bitsim2 = new Bitsim({ rpc: 'http://root:[email protected]:17332' })
const bitsim3 = new Bitsim({ rpc: 'http://root:[email protected]:16332' })
;(async()=>{
await bitsim.init()
// initializes and bootstraps toychain
// 1. funds toychain with coinbase tx
// 2. mines 100 blocks so those coin are spendable
// 3. bootstraps tx tree to avoid mempool limit
await bitsim.last()
// returns last block header from node
await bitsim.mine(n, address)
// mines `n` number of blocks to `address`
// parameters are optional. will use default if blank
await bitsim.add(n, prototype)
// adds `n` data-only transactions to mempool with prototype (output array)
await bitsim.fork(height)
// creates fork at given block `height` by invalidating `height + 1`
await bitsim.rpc(method, [params])
// return arbitrary rpc method response. accepts array of params or no params
})()
;(async()=>{
await bitsim.getRandomBlock(max)
// provides random block height and hash from chain within limit
// useful for creating tests
await bitsim.getLatestHeader()
// wrapper for `getbestblockhash` rpc call
await bitsim.getBlockHeader()
// wrapper for `getblockheader` rpc call
await bitsim.getMempoolInfo()
// wrapper for `getmempoolinfo` rpc call
await bitsim.getRawMempool()
// wrapper for `getrawmempool` rpc call
await bitsim.getBlockHash()
// wrapper for `getblockhash` rpc call
await bitsim.invalidateBlock()
// wrapper for `invalidateBlock` rpc call
})()
NOTE: Bitsim works great when integrated with other unit testing frameworks, like TAPE.
pass configuration options to bitsim as an object on initialization:
const bitsim = new Bitsim({
mine: 1,
delay: 1000,
rpc: 'http://root:[email protected]:18332',
xpriv: 'xprv9s21ZrQH143K2AUh9yj3SmnzFVpHFgfGh23tz9iQb6p86yee29B1CcUenjSvWUFtNQ6oBho8PwPZNPi758kTFvJnxs1SoYbtUbyZeTK9zBC'
})
NOTE: The above represents the default configuration, and need not be specified for most basic single-player mode use cases.
When running Bitsim in multi peer network mode, the provided script provides simple example but you may customize the docker-compose.yml
as desired.