Miner ID

The following instructions describe installing Miner ID using tools available in most mainstream Linux distributions. We assume you use a Bourne-like shell such as bash.

The BRFC (Bitcoin Request For Comment) specification can be found here.

The open source code of the implementation can be found here.

Support

For support and general discussion of both standards and reference implementations please join the following telegram group.

Build from source

Requirements

For development, you will only need Node.js (minimum 10.12.0) and a node global package, NPM, installed in your environment.

Node

  • Node installation on Windows

Just go on official Node.js website and download the installer. Also, be sure to have git available in your PATH, npm might need it (You can find git here).

  • Node installation on Ubuntu

You can install nodejs and npm easily with apt install, just run the following commands.

```console
$ sudo apt install nodejs
$ sudo apt install npm
```
  • Other Operating Systems

You can find more information about the installation on the official Node.js website and the official NPM website.

Install

$ git clone https://github.com/bitcoin-sv/minerid-reference.git
$ cd minerid-reference
$ npm install

Configuration

Create a config.json and edit it with your settings:

  • change port
  • change minerIdDataPath which stores user's miner IDs
  • change keystore which stores miner ID private keys
  • change network (mainnet="livenet" | testnet="testnet" | regtest="regtest")
  • change Bitcoin RPC parameters:
  • rpcHost
  • rpcPort
  • rpcUser
  • rpcPassword

Running the project

To run API server:

$ npm start

To run CLI:

$ npm run cli

Testing

$ npm test

Docker

Build Image

You can build the image yourself with your own modifications or own configurations.

$ docker build . -t minerid_reference:1.1.1

Pull Image

You can also pull it from the public Docker Hub repository for Miner ID here.

$ docker pull bitcoinsv/minerid:1.1.1

Run with Docker Compose

Example docker-compose file:

version: "3.8"
services:
  minerid:
    image: bitcoinsv/minerid:1.1.1
    ports:
      - 9002:9002
    restart: always
    environment:
      NODE_CONFIG: '{
        "bitcoin": {
        "rpcHost":"host.docker.internal"
        },
        "network": "regtest"
        }'
    volumes:
      - minerid:/root/.keystore
      - minerid:/root/.minerid-client
volumes:
  minerid:
    external: false

Since Miner ID is essentially a service built around a private key (Miner ID) we are running the container with volumes in order to avoid the situation where the container falls over for some reason and the private key is lost. In the environment variables, we are specifying which network (livenet (or mainnet), testnet, or regtest) and what Bitcoin node RPC parameters and credentials to use by passing them to NODE_CONFIG.

Initial Setup

Once the docker container is running, you will need to setup and configure your Miner ID by generating a Miner ID private key as well as setting up your Validity Check Transaction output (VCTx). You can do that using docker exec:

$ docker exec -it <CONTAINER> bash

[email protected]:/app#

Then run the cli commands to setup and configure the above:

[email protected]:/app# npm run cli -- generateminerid --name testMiner
[email protected]:/app#  npm run cli -- generatevctx --name testMiner

If you are running on livenet (mainnet), follow the instructions to fund your VCTx.

Using Miner ID API

Once your Miner ID service is setup and running, you will need to call its exposed API from your pool software to include Miner ID in your coinbase transactions. You will also need to call it from mAPI if you want to sign your mAPI responses. The Miner ID API is defined here as well as below:

Implementation

The REST API has 4 endpoints:

1. GET /opreturn/:alias/:blockHeight([0-9]+)

alias: Miner ID alias
blockHeight: block height which Miner ID document is created for/at

returns Miner ID output (locking) script hex string for an alias Miner ID at height blockHeight

Example

2. POST /coinbase2

body:

{ 
  "blockHeight": number,
  "alias": string,
  "coinbase2": string,
  "jobData": {
    "miningCandidate": {},
    "getInfo": {},
    "feeSpec": {}
  }
}

returns updated coinbase2 with the Miner ID output included

FieldFunction
blockHeightHeight of the block which the coinbase transaction will be in
aliasAlias of the Miner ID
coinbase2Second part of the coinbase (coinb2) as shown in the stratum protocol
jobDataData specific to a mining job to be added to the Miner ID coinbase document throught the extensions
miningCandidateBitCoin RPC getminingcandidate response
getInfoBitCoin RPC getinfo response
feeSpecmAPI default fees

Note: The coinbase transaction is split up in the stratum protocol as follows:

cb tx
Example
{ 
    "blockHeight": 100, 
    "alias": "testMiner", 
    "coinbase2": "ffffffff011a0a5325000000001976a9145deb9155942e7d38febc15de8870222fd24d080e88ac00000000", 
    "jobData": {
        "miningCandidate": {
          "id": "e706b0e6-793b-448f-a1ae-8ef54459eb72",
          "prevhash": "70f5701644897c92b60e98dbbfe72e1cfd7a2728c6fa3a29c4b4f6e986b0ccaa",
          "coinbaseValue": 5000000974,
          "version": 536870912,
          "nBits": "207fffff",
          "time": 1590152467,
          "height": 106,
          "num_tx": 4,
          "sizeWithoutCoinbase": 1052,
          "merkleProof": [
            "9bd12ce6508574b3163aadb14eab7bd862306da85b221eb284fb41d6012db98f",
            "56f04cc78ac493defced65dd58f4437c67bcc697b59778b0cd96c3c64c1b0bbf"
          ]
        },
        "getInfo": {
          "version": 101000300,
          "protocolversion": 70015,
          "walletversion": 160300,
          "balance": 199.99997068,
          "blocks": 104,
          "timeoffset": 0,
          "connections": 4,
          "proxy": "",
          "difficulty": 4.656542373906925e-10,
          "testnet": false,
          "stn": false,
          "keypoololdest": 1575386196,
          "keypoolsize": 1999,
          "paytxfee": 0.00000000,
          "relayfee": 0.00000250,
          "errors": "",
          "maxblocksize": 9223372036854775807,
          "maxminedblocksize": 128000000,
          "maxstackmemoryusagepolicy": 100000000,
          "maxstackmemoryusageconsensus": 9223372036854775807
        },
        "feeSpec": {
          "fees": [
            {
              "feeType": "standard",
              "miningFee": {
                "satoshis": 1,
                "bytes": 1
              },
              "relayFee": {
                "satoshis": 1,
                "bytes": 10
              }
            },
            {
              "feeType": "data",
              "miningFee": {
                "satoshis": 2,
                "bytes": 1000
              },
              "relayFee": {
                "satoshis": 1,
                "bytes": 10000
              }
            }
          ]
        }
    }
}

3. GET /opreturn/:alias/rotate

alias: Miner ID alias

rotates the Miner ID key for an alias Miner ID

Example
$ curl localhost:9002/opreturn/testMiner/rotate

OK

4. GET /minerid/:alias

alias: Miner ID alias

returns compressed public key (33 byte) hex string for an alias Miner iD

Example
$ curl localhost:9002/minerid/testMiner

02644f5000535bbc135f9c8613f86f10c66a4a773eda5e913eff64eb328bc6326a

5. GET /minerid/:alias/sign/:hash

alias: Miner ID alias
hash: SHA256 hash (32 byte hex string) to be fed to ECDSA signing algorithm

returns hash signature (71-73 byte hex string) using an alias Miner ID

Example
$ curl localhost:9002/minerid/testMiner/sign/02644f5000535bbc135f9c8613f86f10c66a4a773eda5e913eff64eb328bc632

3045022100e0f86a5b1748ae48b0d10ea305202769d754071272cba0fbb82f74f8e8da8b530220494351742f3ba9e51b155df15b13f27c927d21956822aedcbb7d179c66d4d4c0