Mining Pool protocol
General
Client modes
The Nimiq Mining Pool protocol currently describes two client modes: smart and nano.
smart
In smart-mode, the client is fully responsible for creating blocks.
The client operates as a solo-miner would do (and is also capable of doing a graceful fallback to solo mining).
The server only describes the values to be used as a miner address and in the extraData
field of a block.
The smart-mode Pool Miner requires a Nimiq light- or full-node.
nano
In nano-mode, the client only validates that the pool asks for the correct chain to be operated on.
The server provides all necessary details for the client to build the block, as long as it operates on a chain known to the client.
This mode is similar to getblocktemplate
-based protocols on Bitcoin.
The nano-mode Pool Miner requires a Nimiq node of any kind, a nano-node is sufficient.
Network communication
A secure websocket connection is used as a transport layer for client-server communication. All messages are exchanged as a single WebSocket frame.
Messages
All messages follow the same structure: they consist of a JSON-encoded object with a property named message
as well as message specific properties.
register
Send by client directly after connecting to the server.
Parameters
Parameter | Type | Description |
---|---|---|
mode |
string, nano or smart |
The mode this client uses |
address |
string | The address (in IBAN-style format) that should be rewarded for the miner actions |
deviceId |
number, uint32 | The clients device id. This ID should be unique for the device and stored, such that it stays the same after restarts |
deviceData |
object, optional | A JSON object including stats about the device. The format of this JSON should be defined by the pool operator |
genesisHash |
string | Base64 encoded hash of the genesis block used by the client |
Example
{
"message": "register",
"mode": "nano",
"address": "NQ07 0000 0000 0000 0000 0000 0000 0000 0000",
"deviceId": 12345678,
"deviceData": {
"groupLabel": "AWS Skylakes"
},
"genesisHash": "Jkqvik+YKKdsVQY12geOtGYwahifzANxC+6fZJyGnRI="
}
registered
Sent by the server after a succesful registration. Does not include parameters.
Example
{
"message": "registered"
}
settings
Sent by the server to announce new mining settings.
Parameters
Parameter | Type | Description |
---|---|---|
address |
string | The address (in IBAN-style format) that the client should use as a miner address for future shares |
extraData |
string | Base64 encoded buffer that the client should use in the extraData field for future shares |
targetCompact |
number, uint32 | The maximum allowed hash value for future shares, in compact form |
nonce |
number, uint64 | A number used once that is associated with this connection |
Example
{
"message": "settings",
"address": "NQ07 0000 0000 0000 0000 0000 0000 0000 0000",
"extraData": "J8riQiN1lgXT6QYlsdWMKA+qEWxCPYycjZ19zsk1...",
"targetCompact": 520159232,
"nonce": 1030036789885656
}
new-block
(nano)
Sent by the server to announce a new block that should be used by a client running in nano-mode.
Parameters
Parameter | Type | Description |
---|---|---|
bodyHash |
string | Base64 encoded hash of the block body |
accountsHash |
string | Base64 encoded hash of the accounts tree after applying the block body |
previousBlock |
string | Base64 encoded light block that is the predecessor of the block to be mined |
Example
{
"message": "new-block",
"bodyHash": "rCBGsSJGOOo82af+MhRXb7Dj+lb0oRzrN0EXBg7Jh4g=",
"accountsHash": "9GgRxMDSVUpePCyUDKuAw3hmHeMEj7Y77GsWEssd2qU=",
"previousBlock": "AAHL9kSzaU/uVRSsBVRSlYrx7Dw7NUSFDCWIDhY/..."
}
share
Sent by client when a valid share was found.
Parameters (nano)
Parameter | Type | Description |
---|---|---|
block |
string | Base64 encoded light block |
Parameters (smart)
Parameter | Type | Description |
---|---|---|
blockHeader |
string | Base64 encoded block header |
minerAddrProof |
string | Base64 encoded inclusion proof for the minerAddr field in the block body |
extraDataProof |
string | Base64 encoded inclusion proof for the extraData field in the block body |
block |
string, optional | Base64 encoded full block. May only be sent if the block is a valid block so that the pool server is faster in picking it up |
Example (nano)
{
"message": "share",
"block": "AAHL9kSzaU/uVRSsBVRSlYrx7Dw7NUSFDCWIDhY/..."
}
Example (smart)
{
"message": "share",
"blockHeader": "AAHL9kSzaU/uVRSsBVRSlYrx7Dw7NUSFDCWIDhY/...",
"minerAddrProof": "IXd9Hbms/FWTUl5YEYa5ztf6N9eIz+nIfswDOqGk...",
"extraDataProof": "aZiypZ9S4qvSYbG4dBX4ww9TwOdKeLB+KRwNc0eP..."
}
error
Sent by the server if the client sent an invalid share.
The server may send this message at most once per share
.
Parameters
Parameter | Type | Description |
---|---|---|
reason |
string | A user-readable string explaining why the server denied the share |
Example
{
"message": "error",
"reason": "Invalid PoW"
}
balance
Sent by the server to announce the balance that is currently hold by the pool for the address the user announced on register
.
The server may send this message at any time after the client registered. A new balance
message does not imply any balance changes.
Parameters
Parameter | Type | Description |
---|---|---|
balance |
number | The current balance of the user in the smallest possible unit. This includes funds that are not yet confirmed on the blockchain |
confirmedBalance |
number | The current balance of the user in the smallest possible unit. This only includes funds that operator considers confirmed and are available for payout |
payoutRequestActive |
boolean | true , if there is a payout request waiting for the user, false otherwise |
Example
{
"message": "balance",
"balance": 123010221,
"confirmedBalance": 122010202,
"payoutRequestActive": false
}
payout
Sent by the client to request payout from the server. Depending on server configuration, manual payout may be suspect to an additional fee.
Parameters
Parameter | Type | Description |
---|---|---|
proof |
string | Base64 encoded signature proof of the string POOL_PAYOUT , concatenated with the byte representation of the connection nonce. |
Example
{
"message": "payout",
"proof": "J4VEpFwKNoklkyeUCvzBvixate3yPbDyYfWSusF/..."
}