My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more
Interacting with a Bitcoin SPV node

Interacting with a Bitcoin SPV node

Jesse Ojih's photo
Jesse Ojih
·Jul 14, 2022·

7 min read

First of, let's define some common terms before diving into the main topic.

Blockchain Basics:

A blockchain is a public database that is updated and shared across many computers in a network.

A "Block" refers to data and state being stored in consecutive groups known as "Blocks". When you send BTC to someone else, the transaction data needs to be added to a block to be successful.

A "Chain" refers to how each block cryptographically references it's parent block. Blocks get chained together all linking to the genesis block, the data in a block cannot be changed without changing all subsequent blocks, hence why the blockchain is so secure.

Every computer in the network must agree upon each new block. These computers are known as "nodes". They ensure everyone interacting with the blockchain has the same data.

When you send BTC to someone, the transaction must be mined and included in a new block. The updated state is then shared with the entire network.

How Bitcoin works

Bitcoin uses a shared public ledger on which the entire Bitcoin network depends on. In Bitcoin, a transaction is a transfer of value between Bitcoin wallets that gets included in the blockchain.

Bitcoin wallets keeps a secret data called the a private key or seed, which is used to sign transactions, providing a mathematical proof to prove the transaction was created by the owner of the wallet. The signature also prevents the transaction from being altered by anybody once it has been issued. All valid transactions are broadcasted to the network waiting for confirmation by nodes through a process called mining.

Full node vs SPV node

A full blockchain node verifies a transaction by checking the chain of thousands of blocks below it and checks that UTXO is not spent.

A Simplified Payment Verification (SPV) node are clients or nodes that verifies Bitcoin transactions without running a full network node by downloading Block headers instead of a full Block.

Introduction to Bcoin

Bcoin is an advanced full-node implementation built with Javascript/C/C++/Node.js. It is easier to use, faster to learn, well documented and can be used as a Simple Verification Node for the Bitcoin network. Read More on Bcoin

Interacting with the Bcoin SPV node

This article is mainly about interacting with an SPV node. For a well detailed explanation on how to deploy and run an SPV node on an AWS EC2 instance. Click here

The Bcoin node API

The Bcoin node HTTP API server listens on the following basic ports:

  • Port 8332 for main network
  • Port 18332 for testnet network

Authentication:

Authentication with the Bcoin API server is done with an API key, which is set when setting up and deploying the Bcoin node. Read More

Interaction:

Interaction with Bcoin can be done through both REST API and RPC. We will make use of REST API in this article.

Request format:

http(s)://x-api_key@host_ip:port

  • api_key: Bcoin node API Key
  • host_ip: EC2 or local public IP of Bcoin host server
  • port: Network port to send request to

Read how to deploy

Example Request:

Getting Bcoin Node info running locally on the testnet network.

$ curl http://x-123456@127.0.01:18332/

Example Response:

{
    "result": {
        "version": "2.2.0",
        "network": "testnet",
        "chain": {
            "height": 2283938,
            "tip": "000000000000005b6bc94875ce7c4aaa10dc68c6f96999ab8d866a4f937cfa88",
            "progress": 1
        },
        "indexes": {
            "addr": {
                "enabled": false,
                "height": 0
            },
            "tx": {
                "enabled": false,
                "height": 0
            },
            "filter": {
                "enabled": false,
                "height": 0
            }
        },
        "pool": {
            "host": "0.0.0.0",
            "port": 18333,
            "agent": "/bcoin:2.2.0/",
            "services": "1000",
            "outbound": 8,
            "inbound": 0
        },
        "mempool": {
            "tx": 0,
            "size": 0,
            "orphans": 0
        },
        "time": {
            "uptime": 532593,
            "system": 1656878976,
            "adjusted": 1656878976,
            "offset": 0
        },
        "memory": {
            "total": 109,
            "jsHeap": 22,
            "jsHeapTotal": 28,
            "nativeHeap": 81,
            "external": 8
        }
    }
}

Some Basic Node request:

  • Get a transaction by hash

Format:

$ curl http://x-123456@127.0.01:18332/tx/:hash

hash: Bitcoin transaction hash

Example Request:

$ curl http://x-123456@127.0.01:18332/tx/77a39583060aa3ff2a705d401fea0c07e77e95d66cc10b744dc95098cad1bee1

{
  "hash": "77a39583060aa3ff2a705d401fea0c07e77e95d66cc10b744dc95098cad1bee1",
  "witnessHash": "130bd86dccf06142b6134c7c38997d8babc2104a94d7a84da021d587740ed1c8",
  "fee": 1740,
  "rate": 9942,
  "mtime": 1571763474,
  "height": 530,
  "block": "34d0385c667319c5225c7f82e025681bae2fb5df28809cc7cf432b491125c83c",
  "time": 1571760040,
  "index": 8,
  "version": 1,
  "inputs": [
    {
      "prevout": {
        "hash": "9d2330c36814d20ccdba1b6fc5153ed3b294cb34fa99fc8199552014250ea285",
        "index": 3
      },
      "script": "",
      "witness": "02473044022008765f15a62f283c06082dfea6a6f413eae4190dbbfd57efae1813432b66613e0220163b708d4e1ccd6a439da2d222f72e4231bdfd877fcdfb73ac85566e6358c559012103d2d0677a136821cb92361501570173e2c6b0d8b12e584737ffc991d2d1ccf026",
      "sequence": 4294967295,
      "coin": {
        "version": 1,
        "height": 528,
        "value": 34297185559,
        "script": "0014268a968f7d4d1d72bbecc0ebca21d890901ba312",
        "address": "bcrt1qy69fdrmaf5wh9wlvcr4u5gwcjzgphgcjswyuvn",
        "coinbase": false
      }
    }
  ],
  "outputs": [
    {
      "value": 37547,
      "script": "00143ce6c756ef2f35d61aab99d1619aab2f48da6987",
      "address": "bcrt1q8nnvw4h09u6avx4tn8gkrx4t9ayd56v86q7ceg"
    },
    {
      "value": 50131,
      "script": "76a914e53103ac18b5d274dcea14e6b0c856182ce7021688ac",
      "address": "n2QokZQd8Fn6a82vwXtndYy88HeUk3BZio"
    },
    {
      "value": 34297096141,
      "script": "0014f0ddfca1c6023538c032f6fb46a35703099319fe",
      "address": "bcrt1q7rwlegwxqg6n3spj7ma5dg6hqvyexx07zmt40j"
    }
  ],
  "locktime": 0,
  "hex": "0100000000010185a20e251420559981fc99fa34cb94b2d33e15c56f1bbacd0cd21468c330239d0300000000ffffffff03ab920000000000001600143ce6c756ef2f35d61aab99d1619aab2f48da6987d3c30000000000001976a914e53103ac18b5d274dcea14e6b0c856182ce7021688accd2744fc07000000160014f0ddfca1c6023538c032f6fb46a35703099319fe02473044022008765f15a62f283c06082dfea6a6f413eae4190dbbfd57efae1813432b66613e0220163b708d4e1ccd6a439da2d222f72e4231bdfd877fcdfb73ac85566e6358c559012103d2d0677a136821cb92361501570173e2c6b0d8b12e584737ffc991d2d1ccf02600000000",
  "confirmations": 6
}
  • Get transaction by address

Format:

$ curl http://x-123456@127.0.01:18332/tx/address/:address

address: Bitcoin wallet address

Example Request:

$ curl http://x-123456@127.0.01:18332/tx/address/bcrt1q8nnvw4h09u6avx4tn8gkrx4t9ayd56v86q7ceg

[
  {
    "hash": "77a39583060aa3ff2a705d401fea0c07e77e95d66cc10b744dc95098cad1bee1",
    "witnessHash": "130bd86dccf06142b6134c7c38997d8babc2104a94d7a84da021d587740ed1c8",
    "fee": 1740,
    "rate": 9942,
    "mtime": 1571763513,
    "height": 530,
    "block": "34d0385c667319c5225c7f82e025681bae2fb5df28809cc7cf432b491125c83c",
    "time": 1571760040,
    "index": 8,
    "version": 1,
    "inputs": [
      {
        "prevout": {
          "hash": "9d2330c36814d20ccdba1b6fc5153ed3b294cb34fa99fc8199552014250ea285",
          "index": 3
        },
        "script": "",
        "witness": "02473044022008765f15a62f283c06082dfea6a6f413eae4190dbbfd57efae1813432b66613e0220163b708d4e1ccd6a439da2d222f72e4231bdfd877fcdfb73ac85566e6358c559012103d2d0677a136821cb92361501570173e2c6b0d8b12e584737ffc991d2d1ccf026",
        "sequence": 4294967295,
        "coin": {
          "version": 1,
          "height": 528,
          "value": 34297185559,
          "script": "0014268a968f7d4d1d72bbecc0ebca21d890901ba312",
          "address": "bcrt1qy69fdrmaf5wh9wlvcr4u5gwcjzgphgcjswyuvn",
          "coinbase": false
        }
      }
    ],
    "outputs": [
      {
        "value": 37547,
        "script": "00143ce6c756ef2f35d61aab99d1619aab2f48da6987",
        "address": "bcrt1q8nnvw4h09u6avx4tn8gkrx4t9ayd56v86q7ceg"
      },
      {
        "value": 50131,
        "script": "76a914e53103ac18b5d274dcea14e6b0c856182ce7021688ac",
        "address": "n2QokZQd8Fn6a82vwXtndYy88HeUk3BZio"
      },
      {
        "value": 34297096141,
        "script": "0014f0ddfca1c6023538c032f6fb46a35703099319fe",
        "address": "bcrt1q7rwlegwxqg6n3spj7ma5dg6hqvyexx07zmt40j"
      }
    ],
    "locktime": 0,
    "hex": "0100000000010185a20e251420559981fc99fa34cb94b2d33e15c56f1bbacd0cd21468c330239d0300000000ffffffff03ab920000000000001600143ce6c756ef2f35d61aab99d1619aab2f48da6987d3c30000000000001976a914e53103ac18b5d274dcea14e6b0c856182ce7021688accd2744fc07000000160014f0ddfca1c6023538c032f6fb46a35703099319fe02473044022008765f15a62f283c06082dfea6a6f413eae4190dbbfd57efae1813432b66613e0220163b708d4e1ccd6a439da2d222f72e4231bdfd877fcdfb73ac85566e6358c559012103d2d0677a136821cb92361501570173e2c6b0d8b12e584737ffc991d2d1ccf02600000000",
    "confirmations": 6
  },
  ...
]
  • Get UTXO by txid or index: Format:
$ curl http://x-123456@127.0.01:18332/coin/:hash/:index

hash: Transaction hash

index: UTXO index in transaction

Example Request:

$ curl http://x-123456@127.0.01:18332/coin/53faa103e8217e1520f5149a4e8c84aeb58e55bdab11164a95e69a8ca50f8fcc/0

{
  "version": 1,
  "height": 533,
  "value": 67377,
  "script": "76a9147356fde8f0a321dd114d947495d1f4b9f3cb050088ac",
  "address": "mr2pDQvLN7eGv6xinBgSUmQpYSYdTEWyTf",
  "coinbase": false,
  "hash": "c747afe7aea229ae2aed7135eb768fd2dc1d8172cd7463bf3906e8321baa5608",
  "index": 0
}
  • Get a Block by hash or height:

Format:

$ curl http://x-123456@127.0.01:18332/block/:block

block: Block hash or height

Example Request:

$ curl http://x-123456@127.0.01:18332/block/78f86c294d1ffc640f1783e2b3cc3dcdfbe1da9fe885f35de286f94db8cfac72 # by hash

$ curl http://x-123456@127.0.01:18332/block/50 # by height

{
  "hash": "78f86c294d1ffc640f1783e2b3cc3dcdfbe1da9fe885f35de286f94db8cfac72",
  "height": 50,
  "depth": 484,
  "version": 536870912,
  "prevBlock": "4e186ead55dfe014baee8bab96805c88c03032ba1e92be86709ca9f65ea5003a",
  "merkleRoot": "5bca36ac149947e8f545d28ae2d34b6f6f170d36dd5289766e08813f5d183678",
  "time": 1571759960,
  "bits": 545259519,
  "nonce": 0,
  "txs": [
    {
      "hash": "5bca36ac149947e8f545d28ae2d34b6f6f170d36dd5289766e08813f5d183678",
      "witnessHash": "c3401a27680aebb0603f50c0bafbe22c492ec9e65aea754a179f10b3f537d2c6",
      "fee": 0,
      "rate": 0,
      "mtime": 1571762225,
      "index": 0,
      "version": 1,
      "inputs": [
        {
          "prevout": {
            "hash": "0000000000000000000000000000000000000000000000000000000000000000",
            "index": 4294967295
          },
          "script": "01320e6d696e65642062792062636f696e0431d5f7bf080000000000000000",
          "witness": "01200000000000000000000000000000000000000000000000000000000000000000",
          "sequence": 4294967295,
          "address": null
        }
      ],
      "outputs": [
        {
          "value": 5000000000,
          "script": "76a91415f34e5cc7c4d7cc5a896611af8fb242847e003d88ac",
          "address": "mhX1xHbKGzw3r8FoN5bUkmRixHPEDNywxh"
        },
        {
          "value": 0,
          "script": "6a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9",
          "address": null
        }
      ],
      "locktime": 0,
      "hex": "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff1f01320e6d696e65642062792062636f696e0431d5f7bf080000000000000000ffffffff0200f2052a010000001976a91415f34e5cc7c4d7cc5a896611af8fb242847e003d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"
    }
  ]
}

The wallet client

The Bcoin wallet client is a section of a Bcoin node for managing Bitcoin wallets, signing, broadcasting and receiving transactions. The wallet client also takes care of the hassel of managing private keys for the created wallets.

The wallet HTTP server listens on it's own port, separate from the node's server. By default the wallet server listens on these localhost ports

  • Port 8334 for main
  • Port 18334 for testnet

Bcoin maintains a wallet database which contains every wallet. Wallets are uniquely identified by an id and the walletdb is created with a default id of primary.

Wallets in Bcoin uses BIP44, the wallets database can contain many different wallets, with many accounts, with many different addresses for each account.

- Creating a wallet:

Create a new wallet with a specified ID.

Parameters:

  • id: Wallet using ID
  • passphrase: A strong passphrase to encrypt account

Example request: create-wallet.png

Example response:

{
  "network": "testnet",
  "wid": 11,
  "id": "newWallet",
  "watchOnly": true,
  "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
  }
}

NOTE: wallet-123 in the request URI is the unique ID of wallet passed when creating the wallet, replace with your wallet ID.

- Get wallet info

Get the wallet info by ID.

Example request:

get-wallet-info.png

Example request:

{
  "network": "regtest",
  "wid": 0,
  "id": "primary",
  "watchOnly": false,
  "accountDepth": 1,
  "token": "4d9e2a62f67929340b8c600bef0c965370f29cc64afcdeb7aea9cb52906c1d27",
  "tokenDepth": 13,
  "master": {
    "encrypted": true,
    "until": 0,
    "iv": "e33424f46674d4010fb0715bb69abc98",
    "algorithm": "pbkdf2",
    "n": 50000,
    "r": 0,
    "p": 0
  },
  "balance": {
    "tx": 5473,
    "coin": 5472,
    "unconfirmed": 1504999981750,
    "confirmed": 1494999998350
  }
}

- Get wallet balance

Get wallet balance by ID.

Example request:

get-wallet-balance.png

Example response:

{
  "account": 0,
  "tx": 307,
  "coin": 287,
  "unconfirmed": 1122500000000,
  "confirmed": 1122500000000
}

Generate Receiving address

Generate receiving address for wallet by wallet ID.

Example request:

get-wallet-address.png

Example response:

{
  "name": "default",
  "account": 0,
  "branch": 0,
  "index": 3,
  "witness": false,
  "nested": false,
  "publicKey": "03af169e5a186bbd7b380cb4553c72af243e18f243785b1597f192bbedd4a94fc3",
  "script": null,
  "program": null,
  "type": "pubkeyhash",
  "address": "n2eoT9D8txT5ZymDvCFPA8PHs2CmTV6oJT"
}

- Send Transaction:

Send Bitcoin from wallet to address.

Parameters:

  • rate: Rate of transaction fees.
  • value: Amount of Bitcoin to send (in Satoshis).
  • destination: Destination address for transaction.
  • passphrase: Wallet secret passphrase.

Example request:

send-transaction.png

Example response:

{
  "hash": "3f61cbbe01ca9eb7eb0fb8c37f15e92d2fee8c28ea54fef5b7bc89eee219074b",
  "witnessHash": "3f61cbbe01ca9eb7eb0fb8c37f15e92d2fee8c28ea54fef5b7bc89eee219074b",
  "fee": 3840,
  "rate": 30000,
  "mtime": 1571766790,
  "version": 1,
  "inputs": [
    {
      "prevout": {
        "hash": "4e6c7db14b22e39ca800b0eb83d698619849ac3245408cf03ae5dc752e2d884c",
        "index": 0
      },
      "script": "",
      "witness": "00",
      "sequence": 4294967295,
      "coin": {
        "version": 1,
        "height": 746,
        "value": 312500000,
        "script": "00201e669358ab0b70bbdf63ac7abc442ee1b1f6f0fe24b1d67b2e3527ffac664c39",
        "address": "bcrt1qrenfxk9tpdcthhmr43atc3pwuxcldu87yjcav7ewx5nlltrxfsustr8wj5",
        "coinbase": true
      }
    }
  ],
  "outputs": [
    {
      "value": 5000000,
      "script": "76a914061270cea3bdd77a5442657d177f4490642e7a2288ac",
      "address": "mg54SV2ZubNQ5urTbd42mUsQ54byPvSg5j"
    },
    {
      "value": 307496160,
      "script": "0020485f95ef73a1f444cbbfdb7ff1f43c7e34c069d25a823026d3513cfa64cfd677",
      "address": "bcrt1qfp0etmmn586yfjalmdllrapu0c6vq6wjt2prqfkn2y705ex06ems39f93c"
    }
  ],
  "locktime": 0,
  "hex": "01000000014c882d2e75dce53af08c404532ac49986198d683ebb000a89ce3224bb17d6c4e0000000000ffffffff02404b4c00000000001976a914061270cea3bdd77a5442657d177f4490642e7a2288ace004541200000000220020485f95ef73a1f444cbbfdb7ff1f43c7e34c069d25a823026d3513cfa64cfd67700000000"
}

- Listening for incoming transaction on wallets:

How to listen for incoming transactions on wallets:

listen-for-transactions.png

For more information on the Bcoin Node Click Here

Thank you.