This part explore some feature offered by Bcoin. Bcoin preliminarily developed as JavaScript library. But since i'm not JavaScript developer, i'll just explore
few RPC command and few other functionality offered by Bcoin.
Bcoin on browserOne of the guides mention[1] Bcoin has basic Web UI. I decide to try it, but encountered error. The guide seems to be out of date and i didn't relevant information on Bcoin documentation[2-3], so i decide to give up.
$ npm install webpack webpack-cli
$ npm run webpack-app
npm ERR! Missing script: "webpack-app"
npm ERR!
npm ERR! To see a list of scripts, run:
npm ERR! npm run
npm ERR! A complete log of this run can be found in:
npm ERR! /home/user/.npm/_logs/2022-10-12T06_08_46_856Z-debug-0.log
$ node browser/server.js
node:internal/fs/utils:347
throw err;
^
Error: ENOENT: no such file or directory, open '/home/user/bcoin/browser/app.js'
at Object.openSync (node:fs:594:3)
at Object.readFileSync (node:fs:462:35)
at Object.
(/home/user/bcoin/browser/server.js:8:16)
at Module._compile (node:internal/modules/cjs/loader:1126:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1180:10)
at Module.load (node:internal/modules/cjs/loader:1004:32)
at Function.Module._load (node:internal/modules/cjs/loader:839:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47 {
errno: -2,
syscall: 'open',
code: 'ENOENT',
path: '/home/user/bcoin/browser/app.js'
}
CLITo access Bcoin RPC, you can use either
bcoin-cli or any application/library which support JSON-RPC protocol. Aside from RPC command,
bcoin-cli also mirror some RPC command directly into
bcoin-cli. You can use these command to find out available CLI and RPC command.
$ ./bcoin-cli help
Commands:
$ info: Get server info.
$ broadcast [tx-hex]: Broadcast transaction.
$ mempool: Get mempool snapshot.
$ tx [hash/address]: View transactions.
$ coin [hash+index/address]: View coins.
$ block [hash/height]: View block.
$ header [hash/height]: View block header.
$ filter [hash/height]: View filter.
$ fee [target]: Estimate smart fee.
$ reset [height/hash]: Reset chain to desired block.
$ rpc [command] [args]: Execute RPC command. (`bcoin-cli rpc help` for more)
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc help
Select a command:
stop
help
getblockchaininfo
getbestblockhash
getblockcount
getblock
getblockbyheight
getblockhash
getblockheader
getblockfilter
getchaintips
getdifficulty
getmempoolancestors
getmempooldescendants
getmempoolentry
getmempoolinfo
getrawmempool
gettxout
gettxoutsetinfo
pruneblockchain
verifychain
invalidateblock
reconsiderblock
getnetworkhashps
getmininginfo
prioritisetransaction
getwork
getworklp
getblocktemplate
submitblock
verifyblock
setgenerate
getgenerate
generate
generatetoaddress
estimatefee
estimatepriority
estimatesmartfee
estimatesmartpriority
getinfo
validateaddress
createmultisig
createwitnessaddress
verifymessage
signmessagewithprivkey
setmocktime
getconnectioncount
ping
getpeerinfo
addnode
disconnectnode
getaddednodeinfo
getnettotals
getnetworkinfo
setban
listbanned
clearbanned
getrawtransaction
createrawtransaction
decoderawtransaction
decodescript
sendrawtransaction
signrawtransaction
gettxoutproof
verifytxoutproof
getmemoryinfo
setloglevel
Bcoin RPC also have detailed documentation. But take note it was last updated on October 2019 (equal to bcoin version v2.0.0-dev)[3]. So it's possible some RPC command behavior changed since then.
RPC Calls - Nodegetinfo show basic information about Bcoin node and wallet.
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc getinfo
{
"version": "2.2.0",
"protocolversion": 70015,
"walletversion": 0,
"balance": 0,
"blocks": 758305,
"timeoffset": 0,
"connections": 1,
"proxy": "",
"difficulty": 35610794164371.65,
"testnet": false,
"keypoololdest": 0,
"keypoolsize": 0,
"unlocked_until": 0,
"paytxfee": 0.00005,
"relayfee": 0.00001,
"errors": ""
}
validateaddress used to validate whether an address is valid or not. As expected, Bcoin can verify P2PKH, P2SH and P2WPKH address[4] without problem.
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress 17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem
{
"isvalid": true,
"address": "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem",
"scriptPubKey": "76a91447376c6f537d62177a2c41c4ca9b45829ab9908388ac",
"isscript": false,
"iswitness": false
}
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress 3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX
{
"isvalid": true,
"address": "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX",
"scriptPubKey": "a9148f55563b9a19f321c211e9b9f38cdf686ea0784587",
"isscript": true,
"iswitness": false
}
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
{
"isvalid": true,
"address": "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
"scriptPubKey": "0014751e76e8199196d454941c45d1b3a323f1433bd6",
"isscript": false,
"iswitness": true,
"witness_version": 0,
"witness_program": "751e76e8199196d454941c45d1b3a323f1433bd6"
}
Since i found out Bcoin already support Bech32m, i decide to use some test vector for Bech32m address[5] which represent Taproot/P2TR address on mainnet (which indicated by
bc1p prefix). Unsurprisingly, Bcoin passed the test vector. For valid address, Bcoin showing the address is valid with correct scriptPubKey. For invalid address, Bcoin showing the address is invalid, although it doesn't state the cause/reason.
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6y
{
"isvalid": true,
"address": "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6y",
"scriptPubKey": "5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6",
"isscript": false,
"iswitness": true,
"witness_version": 1,
"witness_program": "751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6"
}
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0
{
"isvalid": true,
"address": "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0",
"scriptPubKey": "512079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"isscript": false,
"iswitness": true,
"witness_version": 1,
"witness_program": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
}
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqh2y7hd
{
"isvalid": false
}
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress bc1p38j9r5y49hruaue7wxjce0updqjuyyx0kh56v8s25huc6995vvpql3jow4
{
"isvalid": false
}
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress bc1pw5dgrnzv
{
"isvalid": false
}
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v8n0nx0muaewav253zgeav
{
"isvalid": false
}
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc validateaddress bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v07qwwzcrf
{
"isvalid": false
}
verifymessage is used to verify signed message. I use 2 recently staked address[6-7] from thread "Stake your Bitcoin address here"[8] as example. Bcoin manage to verify both signed message (from P2PKH and P2WPKH address) without problem. Obviously when i modify the signature/message, Bcoin return
false.
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc verifymessage "bc1qaen0qmpw4j3lu83n7lzg6jncrgry7r7p0eplyl" "Hz1Oiy3eXgwdUNsMxSKA/GJdx8XvDkY+4LrAP9k0yVkKb+OQOl/tMpBE7qU95N5rpR6ztGbCuKOBRnYxDGQ1J9k=" "Today 19/9/2022 I would like to sign my wallet from Electrum."
true
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc verifymessage "17mtDab5mfK9rwup3UDmKCbaeHwuruFZKV" "IN5zxE8FOEhF+ZgFSuILjaQxrgz0Wk8dbnJ8TmqqAC2wCt3JmzciX2hDm1DEhVNntMN9gg57TuwwrhREyObi7TQ=" "Today is 13 Sept, 2022 and this is palle11 of BTT staking this address here as mine."
true
RPC calls - BlockBcoin RPC calls about Bitcoin block is very similar with Bitcoin Core RPC calls. As shown below, i include 2 example which used to
1. Obtain genesis block by combining command
getblockhash and
getblock.
2. Obtain block header of recently mined block by combining command
getblockhash and
getblock.
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc getblock $(./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc getblockhash 0)
{
"hash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
"confirmations": 758308,
"strippedsize": 285,
"size": 285,
"weight": 1140,
"height": 0,
"version": 1,
"versionHex": "00000001",
"merkleroot": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"coinbase": "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73",
"tx": [
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
],
"time": 1231006505,
"mediantime": 1231006505,
"nonce": 2083236893,
"bits": "1d00ffff",
"difficulty": 1,
"chainwork": "0000000000000000000000000000000000000000000000000000000100010001",
"nTx": 1,
"previousblockhash": null,
"nextblockhash": "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048"
}
./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc getblockheader $(./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc getblockhash 758307)
{
"hash": "000000000000000000062cc24b230d35e91802be5c56ecdc8c83335f1a38c817",
"confirmations": 1,
"height": 758307,
"version": 850198532,
"versionHex": "32ad0004",
"merkleroot": "f1348496b539c3ff460915a5c175f791f1605de2193d43ea7212b5256ec31bf8",
"time": 1665558400,
"mediantime": 1665557075,
"nonce": 3182294105,
"bits": "1707e772",
"difficulty": 35610794164371.65,
"chainwork": "000000000000000000000000000000000000000036f62b1a23ff7175f72ac248",
"previousblockhash": "0000000000000000000279315a5d1ae3883db75104eaab9f8ab425eb8447b81b",
"nextblockhash": null
}
RPC calls - Mempoolgetmempoolinfo is used to get statistic of Bcoin mempool. Compared with Bitcoin Core, Bcoin show less information.
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc getmempoolinfo
{
"size": 1926,
"bytes": 9865640,
"usage": 9865640,
"maxmempool": 314572800,
"mempoolminfee": 0.00001
}
$ ./bitcoin-cli getmempoolinfo
{
"loaded": true,
"size": 2001,
"bytes": 834058,
"usage": 4385952,
"total_fee": 0.05797974,
"maxmempool": 1024000000,
"mempoolminfee": 0.00001000,
"minrelaytxfee": 0.00001000,
"unbroadcastcount": 0
}
RPC calls - Networkgetpeerinfo is used to get information of connected node. Just like above example, Bcoin's
getpeerinfo also show less information.
$ ./bcoin-cli --api-key=test_bcoin --http-port=48332 rpc getpeerinfo
[
{
"id": 1,
"addr": "127.0.0.1:8333",
"services": "00000449",
"servicenames": [
"NETWORK",
"WITNESS"
],
"relaytxes": true,
"lastsend": 1665559472,
"lastrecv": 1665559472,
"bytessent": 287895,
"bytesrecv": 4942460,
"conntime": 2550,
"timeoffset": 0,
"pingtime": 0.001,
"minping": 0,
"version": 70016,
"subver": "/Satoshi:23.0.0/",
"inbound": false,
"startingheight": 758301,
"besthash": "000000000000000000062cc24b230d35e91802be5c56ecdc8c83335f1a38c817",
"bestheight": 758307,
"banscore": 0,
"inflight": [],
"whitelisted": false
}
]
$ ./bitcoin-cli getpeerinfo
...
{
"id": 54,
"addr": "127.0.0.1:57226",
"addrbind": "127.0.0.1:8333",
"addrlocal": "127.0.0.1:8333",
"network": "not_publicly_routable",
"services": "0000000000000009",
"servicesnames": [
"NETWORK",
"WITNESS"
],
"relaytxes": true,
"lastsend": 1665559520,
"lastrecv": 1665559516,
"last_transaction": 0,
"last_block": 0,
"bytessent": 5003478,
"bytesrecv": 292272,
"conntime": 1665556921,
"timeoffset": 0,
"pingtime": 0.000206,
"minping": 0.00019,
"version": 70015,
"subver": "/bcoin:2.2.0/",
"inbound": true,
"bip152_hb_to": false,
"bip152_hb_from": false,
"startingheight": 758301,
"synced_headers": 758301,
"synced_blocks": 758301,
"inflight": [
],
"addr_relay_enabled": true,
"addr_processed": 1,
"addr_rate_limited": 0,
"permissions": [
],
"minfeefilter": 0.00000000,
"bytessent_per_msg": {
"addr": 1535,
"blocktxn": 202447,
"cmpctblock": 36546,
"feefilter": 32,
"getheaders": 1053,
"inv": 261388,
"ping": 704,
"pong": 2784,
"sendcmpct": 66,
"sendheaders": 24,
"tx": 4496749,
"verack": 24,
"version": 126
},
"bytesrecv_per_msg": {
"*other*": 21203,
"addr": 55,
"getblocks": 1053,
"getblocktxn": 849,
"getdata": 264008,
"headers": 106,
"inv": 1330,
"ping": 2784,
"pong": 704,
"sendcmpct": 33,
"verack": 24,
"version": 123
},
"connection_type": "inbound"
},
...
ConclusionIt was fun trying Bcoin, even though initial sync/IBD took some time. But clearly Bcoin isn't best option if you only want to run Bitcoin full node. But for JavaScript developer who want to develop software which need data directly from blockchain, Bcoin should be viable choice (with exception of Taproot support).
Some things i like,
- Easy compile and installation process.
- Lots of RPC command which pose similarity with Bitcoin Core RPC.
- Existance of address index.
- Production-ready JavaScript library.
Some things i don't like,
- Some outdated documentation.
- Lots of disk read/write, which significantly slow down sync on HDD.
[1]
https://bcoin.io/guides/browser.html[2]
https://github.com/bcoin-org/bcoin/tree/v2.2.0/docs[3]
https://bcoin.io/api-docs/index.html#introduction[4]
https://en.bitcoin.it/wiki/List_of_address_prefixes[5]
https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki#test-vectors-for-v0-v16-native-segregated-witness-addresses[6]
https://bitcointalksearch.org/topic/m.60965625[7]
https://bitcointalksearch.org/topic/m.60930988[8]
https://bitcointalksearch.org/topic/stake-your-bitcoin-address-here-996318