Getting started with Bcoin (JavaScript Implementation of Full Node)
A Beginner's Guide
In this article, we will walk through "how to install and run a full node of Bitcoin using Bcoin."
We will create a wallet, send some coins and mine some blocks in regtest mode. So, let's start.
Introduction
The Bitcoin blockchain is designed as a decentralised P2P network where nobody owns or controls Bitcoin, and everyone can participate. A full node is a program that fully validates transactions and blocks. By running a Bitcoin full node, you are supporting the Bitcoin network to become more decentralised and fostering the growth of Bitcoin.
What is Bcoin?
'Bcoin' is an alternative implementation of Bitcoin protocol built with Javascript. A full node can be used for full blockchain validation and is aware of all known consensus rules. It is easier to use, faster to learn and more well-documented than competing implementations.
Installation
Bcoin
is meant to be installed via Git for security purposes, as there are security issues when installing via npm.
Installing via Git
$ mkdir Bcoin && cd Bcoin
$ git clone https://github.com/bcoin-org/bcoin
$ cd bcoin
You can also verify signatures using:
$ git log --show-signature
<press q to exit signature log>
Public key fingerprints needed for the verification are available here.
Build and install globally with npm:
$ npm rebuild
$ npm install --global
In Nodejs projects, it's common to use npm install
, which will fetch all the dependencies mentioned in the dependency tree. We are worried about npm as a single central point of failure and how the downloaded source code can be verified. (there have been dependency attacks on Nodejs projects before)
So it's a bit strange but what we do now in bcoin
is COMMIT the node_modules directory directly to the bcoin
main repository. Because of this, the npm install
command is not necessary now. npm rebuild
still is, though, because what that does is compile the native source code (code written in C/C++ in bcrypto and level DB) for the operating system in use.
Run the test locally
So, what are these tests?
The tests are used for several things:
- Preventing regression (if a contributor opens a pull request that breaks a test, there is something wrong with their code that we will likely NOT want to merge)
- Documentation. I know this one seems funny, but sometimes the best way to understand a module is to look at the test. For example, if you read through, you should get a great overview of how to encode and decode Bitcoin addresses using
bcoin
.
From inside the Bcoin
repo directory, Run
$ npm run test
or you can run a single test also
$ npm run test-file test/address-test.js
Now, we are ready to run our bcoin
full node.
Starting up your first bcoin node
If bcoin
is installed globally, bcoin
should be in your PATH. If not, the bcoin
bootstrap script resides in /path/to/bcoin/bin/bcoin
.
We will be running the full node in regtest
mode.
$ bcoin --network=regtest
This will start a bcoin
full node in a local test mode with no peers and 0-difficulty mining. The bcoin
full node will be launched with default options by reading through the configuration guide above, and you can see what other settings are available.
Now in the second terminal, use the bcoin-cli
tool to get node info.
$ bcoin-cli --network=regtest info
You can also set an environment variable, and then you don't need to pass --network=regtest
to every command:
$ export BCOIN_NETWORK=regtest
Now you can run the same command without using --network=regetest
$ bcoin-cli info
Playing with the wallet
By default, the Bcoin
software runs a wallet, and that wallet is initialized on the first launch. The wallet is called primary
and has one account called default
.
Bcoin
uses BIP44 for its wallet structure, and Bcoin
also uses BIP39 seed phrases for its wallets.
Get your wallet's seed phrase
$ bwallet-cli master --id=primary
This command will return a JSON
containing information about your wallet master key.
{
"encrypted": false,
"key": {
"xprivkey": "tprv8ZgxMBicQKsPfNKy1Wf9EV1cTmz1Cmm6MVrvYdgcR6Hf8sEDUAzhnnoiVbw5jejp4EZWXynQEJhB62oSfANpHRAJqfiZarh1gVMowcJZ2Mn"
},
"mnemonic": {
"bits": 128,
"language": "english",
"entropy": "e35833c318d677945ec21efff032bb64",
"phrase": "today screen valid coyote guess sketch kitchen duck zoo light put siege"
}
}
Write down that
seed
phrase and keep it safe! If this weremainnet
, that phrase is how you can backup and restore your wallet!
Get your wallet's current receive address
$ bwallet-cli --id=primary --account=default address
It will return a JSON
response about your current receiving address.
{
"name": "default",
"account": 0,
"branch": 0,
"index": 3,
"witness": false,
"nested": false,
"publicKey": "03af169e5a186bbd7b380cb4553c72af243e18f243785b1597f192bbedd4a94fc3",
"script": null,
"program": null,
"type": "pubkeyhash",
"address": "n2eoT9D8txT5ZymDvCFPA8PHs2CmTV6oJT"
}
Now you have a receiving address, so we can mine some dummy blocks in the current (regtest) network to fund our wallet.
$ bcoin-cli rpc generatetoaddress 10 n2eoT9D8txT5ZymDvCFPA8PHs2CmTV6oJT
this command will mine 10 blocks in the regtest network with the address as your coinbase address. Now we can check our wallet balance.
Check your wallet balance
$ bwallet-cli --id=primary balance --account=default
it will return a JSON
response with your account balance
{
"account": 0,
"tx": 307,
"coin": 287,
"unconfirmed": 1122500000000,
"confirmed": 1122500000000
}
Now let's create a second wallet, one that uses Segregated Witness
. A brief explanation of this wallet type is here but what is more valuable is the list of BIPs ( 141, 144 , 143, and 173) that describe all the technical protocol upgrades.
Creating segwit wallet
You can name this wallet whatever you want (here we are naming it test1).
$ bwallet-cli mkwallet test1 --witness=true
it will return a JSON
response with details of your new wallet,
{
"network": "regtest",
"wid": 11,
"id": "test1",
"watchOnly": false,
"accountDepth": 1,
"token": "489d43e398dad34e69653e5edb5cb39b6d55be3364753c07d084d4b3d0292af7",
"tokenDepth": 0,
"master": {
"encrypted": true,
"until": 1571763677,
"iv": "4e24f2a5908e20da0b8ba3e88dcda272",
"algorithm": "pbkdf2",
"n": 50000,
"r": 0,
"p": 0
},
"balance": {
"tx": 0,
"coin": 0,
"unconfirmed": 0,
"confirmed": 0
}
}
Getting address for this new wallet,
$ bwallet-cli --id=test1 --account=default address
Now, we have our new wallet address, Let's send some coins from our first wallet to the second wallet.
Sending money
$ bwallet-cli send --id=primary --value=1000 --address=<your segwit wallet address>
Now, check the balance of our segwit wallet
.
$ bwallet-cli --id=test1 balance
it shows a JSON
response,
{
"account": -1,
"tx": 1,
"coin": 1,
"unconfirmed": 100000000000,
"confirmed": 0
}
So, we have created two wallets and also sent some regtest coins from one wallet to another, we also mined some regtest blocks.
Thanks for the reading.
References
This post was written at Summer of Bitcoin 2021. Here is the list of references I used.
Special thanks to Matthew Zipkin for being an amazing mentor.