This draft specification is released as an RFC (request for comment) as part of the public review process. Any comments, criticisms or suggestions should be directed toward the issues page on this github repository.
A reference implementation of the Miner ID document server is available at https://github.com/bitcoin-sv/minerid-reference
BRFC | title | authors | version |
---|---|---|---|
6a2e939f8d19 | minerId | nChain | 1.0 |
Miners can identify themselves by including Miner information in transactions within the block. The relevant transactions are pointed to (directly and indirectly) by the coinbase transaction of the block.
The Miner ID is recorded on the BSV main chain (a.k.a active chain), consequently, the Miner ID protocol data present on a forked-branch will be ignored by the processing nodes. Moreover, the Miner ID reputation is built up as a sequence of Miner ID chains recorded on the BSV main chain. The initial miner info document defines the beginning of the first Miner ID chain. The beginning of the following chains is defined by the Miner ID key rotation. The protocol does not support parallel Miner ID chains. Any such occurrence indicates a malicious activity.
The protocol is cryptographically secured by two independent keys: the Miner ID and Revocation Key. The compromised miner can recover his identity if not more than one key is compromised.
Miner ID is a voluntary extra service that miners can offer and is not mandatory.
Miner ID enables miners to build up a reputation over time that increases public confidence in their services, while at the same time protecting miners from manipulation and spoofing. A miner can also include additional information in the miner info document such as services offered, contact information, etc. Third parties can be confident that any message signed using the miner ID private key comes from that miner. It can be further used for chain analysis (e.g. determining the number of blocks mined by a specific miner).
The Miner ID Generator is used to generate the Miner ID output (Miner ID public key and signature); the pool operator can append that output to the coinbase transaction before mining for a new block.
Coinbase Transaction
inputs | outputs | value |
---|---|---|
coinbase |
miner locking script |
reward |
The table below shows the structure of the coinbase transaction, which refers to the transaction containing the miner info document and signature.
Miner ID Coinbase Transaction
inputs | outputs | value |
---|---|---|
coinbase |
miner locking script |
reward |
OP_0 OP_RETURN 0x601dface protocol-id-version miner-info-txid block-bind sig(block-bind) |
0 |
The table below shows the structure of the miner info transaction containing the miner info document and signature.
Miner Info Transaction
inputs | outputs | value |
---|---|---|
... | OP_0 OP_RETURN 0x601dface protocol-id-version miner-info sig(miner-info) |
0 |
... | ... | ... |
The block height is included in the miner info document. The miner info transaction must be included in the same block as the Miner ID coinbase transaction referencing it.
Note that different data elements are encapsulated in Bitcoin PUSHDATA operation as described in this data element framing standard
attribute | description |
---|---|
0x601dface |
4 byte miner ID protocol prefix. |
protocol-id-version |
1 byte protocol prefix version, must be 0. |
miner-info |
The miner info document. It must be included in the first output of the miner info transaction (at the index 0). |
sig(miner-info) |
The signature on miner-info using the private key associated with the miner ID public key defined in miner-info . It must be included in the first output of the miner info transaction (at the index 0).Note: Only the data itself and NOT the PUSHDATA operations in the script are included in the signature message. |
miner-info-txid |
32 byte transaction ID of the transaction containing the miner info document. |
block-bind |
The hash over the modified Merkle root and previous block hash concatenated field, see block binding technique. |
sig(block-bind) |
The signature on block-bind using the private key associated with the miner ID in the miner info transaction. |
The miner info document is a stateless JSON document where a miner includes Miner ID information at a specified block height.
{
"version": string,
"height": number,
"prevMinerId": string,
"prevMinerIdSig": string,
"minerId": string,
"prevRevocationKey": string,
"prevRevocationKeySig": string,
"revocationKey": string,
"revocationMessage": object,
"revocationMessageSig": object,
"minerContact": {
"name": string,
"merchantAPIEndPoint": string,
"<any>": <any>
},
"extensions": {
"authconn": {
"PublicIP": string,
"PublicPort": number
}
}
}
field | status | description |
---|---|---|
version |
required | Miner ID implementation version number. |
height |
required | Block height in which Miner ID document is included. |
prevMinerId |
required | Previous minerId public key, a 33 byte hex string. |
prevMinerIdSig |
required | Signature on message = HASH256(concat(prevMinerId, minerId)) using the private key associated with the prevMinerId public key, 70-72 byte hex (the concatenation is done on the hex encoded bytes). |
minerId |
required | Current Miner ID ECDSA (secp256k1) public key represented in compressed form as a 33 byte hex string. |
prevRevocationKey |
required | Previous revocationKey public key, a 33 byte hex string. |
prevRevocationKeySig |
required | Signature on message = HASH256(concat(prevRevocationKey, revocationKey)) using the private key associated with the prevRevocationKey public key, a 70-72 byte hex string (the concatenation is done on the hex encoded bytes). |
revocationKey |
required | Current revocation key ECDSA (secp256k1) public key represented in compressed form as a 33 byte hex string. |
revocationMessage |
conditionally required | revocationMessage definition |
revocationMessageSig |
conditionally required | revocationMessageSig definition |
minerContact |
optional | Extra miner details (with arbitrary number of subfields, none of which are required). |
extensions |
optional | Additional data defined by MinerId extension BRFCs. This field may be omitted if no extensions are in use. |
The revocation message field to be signed to certify the legitimate miner who wants to revoke past reputation.
The revocationMessage
is a JSON object containing the compromised minerId public key - in the case of complete revocation it is the minerId key defined by the initial Miner ID document:
"revocationMessage": {
"compromised_minerId": string
}
The revocationMessage
field is required in the miner info document only if one of the following occurs: Rolling the Miner ID using Revocation Key or Complete Miner ID Revocation.
The field defines two different signatures on the msg_hash := Hash256(compromised_minerId)
message digest.
The revocationMessageSig
is a JSON object containing two signatures:
"revocationMessageSig": {
"sig1": string,
"sig2": string
}
Note:
sig1
andsig2
are 70-72 byte hex strings.
sig1 := Sign(msg_hash, priv_revocationKey)
, where priv_revocationKey is the private key associated with the revocationKey public key.
sig2 := Sign(msg_hash, priv_minerId)
, where priv_minerId is the private key associated with the miner's:
- current miner ID public key defined in the complete revocation document by the minerId data field, or
- previous miner ID public key defined in the partial revocation document by the prevMinerId data field
The revocation document is a miner info document which does define a partial or complete miner ID key revocation (see 4.4.1 and 4.4.2 sections).
The revocationMessageSig
field is only required if the revocationMessage
field is defined.
field | type | status | description |
---|---|---|---|
dataRefs |
object | optional | See section 7 |
authconn |
object | optional | "PublicIP": string, "PublicPort": number |
The main signature which certifies each and every miner info document is sig(miner-info). All other signatures defined by the protocol are included in the document itself, and thus coupled with the main signature. As a result, the miner ID key is always used to authorise any change in the document.
The base MinerId protocol is intended to be extended with additional information as required. Extensions are out of scope for the base protocol and are described in additional BRFC documents. Extensions along with their BRFCs can be found in the extensions
directory. For more info please check:
Internal extension data can be added in the extensions
field of the miner info document. Each BRFC should encapsulate its additional data within its own JSON document inside the extension
object of the relevant miner info document.
Miners can identify themselves by including some recognisable data (e.g. their name) in the coinbase transaction whenever they mine a block. However, this data can be forged and is not standardised.
The miner ID provides a way of cryptographically identifying miners that cannot be forged unless the Miner ID private key is compromised (known to a 3rd party).
If the miner ID is compromised, a second "revocation" key can be used by the miner to force the roll of the miner ID to a new value chosen by the miner.
It is vital that both keys are not compromised. If both keys are known to a 3rd party then that party can take over the miner ID chain and the legitimate owner cannot do anything about it.
ECDSA (secp256k1) keys used by the MinerID Protocol
Name | Private key* | Public key | Description |
---|---|---|---|
minerId |
Used to sign: a. the miner info document b. the block-bind data c. the revocation message |
Used in the miner info document. | Current MinerID key which identifies a miner. |
prevMinerId |
Certifies minerId key rotation. | Used in the miner info document. | Previous MinerID key. |
revocationKey |
Signs the revocation message. | Used in the miner info document. | Current revocation key. |
prevRevocationKey |
Certifies revocationKey key rotation. | Used in the miner info document. | Previous revocation key. |
* Must be secretly kept.
Note:
1. All the keys are unique. If the private key from the private/public key pair becomes compromised, then the whole key is considered compromised.
2. A Miner ID is the public key of an ECDSA keypair. The Miner ID private key is used to sign a miner info document that is included as an OP_RETURN output of a transaction in a block; the coinbase transaction of the same block points to that transaction.
Keys can be compromised. Many security protocols require keys to be changed at regular intervals to improve security. It is a requirement that the specification supports:
- planned rolling of the miner ID key or revocation key.
- rolling of the miner ID key in response to a spoofed miner ID on the blockchain.
- rolling of the revocation key in response to a data breach.
- complete revocation of a miner ID.
Use case: Create a new Miner ID reputation chain.
The first Miner ID miner info document assigns:
- the same miner ID public key to prevMinerId and minerId fields defined in the protocol (which marks the beginning of the MinerID reputation chain).
- the same revocation public key to prevRevocationKey and revocationKey fields; it also contains prevRevocationKeySig signature to confirm the possession of the corresponding revocation private key.
Note: The prevMinerIdSig field is not defined because prevMinerId == minerId and the miner info document itself is signed by minerId private key.
The protocol assumes that the keys initialised in the first miner info document can be reused by consecutive miner info documents until the key rolling or key revocation occurs.
Use Case: Typically this protocol would be invoked to satisfy security protocols that require that keys be changed at regular intervals, or if it is suspected that someone has knowledge of the miner ID private key who should not have.
The protocol replaces the currently active private/public Miner ID key pair with a new one, and thus the former minerId public key becomes prevMinerId public key in the new miner info document. To authorise the Miner ID Key Rolling procedure the prevMinerIdSig signature must be created and included in the new miner info document. This will prove that the miner possesses the corresponding private key of the public key which is being rotated.
If the prevMinerIdSig is invalid, then the Miner ID Key attached to the block or notification is regarded as invalid and processing proceeds as if the Miner ID document was not present.
Note:
1. The currently active Miner ID key is always the one indicated by the last miner info document recorded on the active chain by the genuine miner.
2. The Miner ID key can be rotated if either its lifespan has elapsed or the key has been classified as compromised.
3. The final signature over the miner info document - sig(miner-info-doc) using the current minerId private key - certifies the MinerID Key Rolling procedure.
Use Case: Typically this protocol would be invoked to satisfy security protocols that require that keys be changed at regular intervals, or if it is suspected that someone has knowledge of the revocation private key who should not have.
The section describes the protocol used to roll the revocation key if there is no active attempt to impersonate the revocation key.
The protocol replaces the currently active private/public revocation key pair with a new one, and thus the former revocationKey public key becomes prevRevocationKey public key in the new miner info document. To authorise the Revocation Key Rolling procedure the prevRevocationKeySig signature must be created and included in the new miner info document. This will prove that the corresponding private key (of the public key which is being rotated) is accessible by the miner.
If the prevRevocationKeySig signature is invalid, then the whole miner info document is considered as invalid.
Note:
1. The currently active revocation key is always the one indicated by the last miner info document recorded on the active chain by the genuine miner.
2. The revocation key can be rotated if either its lifespan has elapsed or the key has been classified as compromised.
3. The final signature over the miner info document - sig(miner-info-doc) using the current minerId private key - certifies the Revocation Key Rolling procedure.
The Miner ID reputation chain is required to be a part of the BSV main chain, and thus any change in the Miner ID protocol data must also be recorded on the BSV main chain. This approach guarantees that new nodes will interpret the Miner ID reputation chain correctly during the IBD process.
Key Revocation is an optional 2-key solution to security issues. The minerId private key is used in the day-to-day operation of miner ID. A separate revocation key-pair is kept in reserve (possibly off-site) to restore compromised or potentially compromised minerIds.
If the revocation key also becomes compromised, then the miner has effectively lost control of his on-chain identity and he will need to rebuild his identity from scratch.
The revocation private key should remain as secure as possible and not be distributed unnecessarily - It is therefore not expected to be available for automated signing. The revocation key can only be defined at the same time as the first minerId in the chain of minerIds, although it can be rotated in the future.
Use Case: Typically this protocol would be invoked if an attacker has generated a block successfully marked with the miner ID belonging to someone else. I.e. The attacker has successfully impersonated the miner. The miner knows exactly which minerId private key has been compromised. The revocation key has NOT been compromised.
The section describes the protocol used to roll the miner ID key using the revocation key.
This type of attack requires the attacker to know the miner ID private key.
The compromised miner can decide to partially revoke its reputation if he knows exactly which minerId private key is compromised in his reputation chain. The partial revocation requires to define the revocationMessage and revocationMessageSig fields as well as to rotate the compromised minerId public key in the next miner info document (the revocation document).
The following example illustrates how to revoke the compromised minerId=mid4 public key first detected in the recent Bn+k block. The Bn+k+1 block contains the miner info revocation document which defines minerId key rotation of the compromised key, as well as revokes miner's compromised reputation starting from the Bn+j block by using revocationMessage and revocationMessageSig.
Note:
1. The partial revocation only applies to the Miner ID reputation recorded on the active chain.
2. Only the current revocationKey private key can be used to sign revocationMessage. The old rotated revocation keys are invalid. In Fig. 5a the current revocation key is rkey1.
3. The revocation message is also being signed by the miner ID private key. In Fig. 5a the private key associated with the current compromised mid4 public key is the right one to use (the mid5 key will become the current uncompromised miner ID key once the revocation document is successfully recorded on the active chain).
4. The final signature over the miner info revocation document - sig(miner-info-doc) - is created using the new minerId=mid5 private key and included in the miner info transaction belonging to the Bn+k+1 block.
Use case: Typically this protocol is invoked when the miner ID is compromised and the policy is to revoke the entire miner ID chain and start a new chain. The miner is uncertain which minerId private key has been compromised in the chain, and thus wants to invalidate the entire chain to prevent the miner's data to be reused by an attacker. The revocation key has NOT been compromised.
The section describes the protocol used to completely revoke the entire Miner ID reputation.
In order to completely revoke the past Miner ID reputation, the miner needs to include the first minerId public key (defined by the initial Miner ID document) in the revocationMessage field and create revocationMessageSig signature. The Miner ID or Revocation Key Rolling doesn't occur in the revocation document. The prevMinerId field is set to the same value as the minerId field. The revocation process is considered as completed when the revocation document is recorded on the active chain. After that, the legitimate miner must setup a new identity from scratch.
The Fig. 5b example shows Bn+k+1 block containing miner info document where complete revocation is defined. After that the miner must to recreate its reputation chain from scratch - what is shown by Bn+k+2 block.
Note:
1. The complete revocation only applies to the Miner ID reputation recorded on the active chain.
2. Only the current revocationKey private key can be used to sign revocationMessage. The old rotated revocation keys are invalid. In Fig. 5b the current revocation key is rkey1.
3. The current revocation keys can be reused by the miner info document defined in the Bn+k+2 block (the first block of the new identity).
4. The revocation message is also being signed by the miner ID private key. In Fig. 5b the private key associated with the current compromised mid4 public key is the right one to use.
5. The final signature over the miner info revocation document - sig(miner-info-doc) - is created using the current minerId=mid4 private key and included in the miner info transaction belonging to the Bn+k+1 block.
Use case: A PoW-independent notification sent by a miner to inform its connection peers about the compromised minerId key. The announcement refers to the Miner ID blocks recorded on the active chain.
To allow instant revocation of the compromised minerId public key the protocol introduces a new P2P revokemid message. It is not expect that the whole network is reachable via P2P messages, and thus the P2P message should be interpreted as an early announcement of the compromised minerId public key. If the given node gets a valid revocation message, then it should invalidate the compromised minerId public key in its own Miner ID database.
The dataRefs
field enables miner info documents to include data contained in other transactions. The miner info document will likely be widely requested by users along with block headers in the future. As such it is in the miner's interests to keep the miner info relatively small. A data reference allows data to be stored in other transactions and consolidated into a miner info document.
The reference points to another transaction output that is expected to contain a JSON object. The contents of that JSON object should be merged into the extensions
field. Note that the signatures are over the original miner info document containing the dataRef object and do not include the data itself. A hash of the data is included through the txid
.
The referenced transaction need not necessarily be included in the same block, allowing old data to be reused.
Note: We do not sign the additional data as the transaction id serves as a binding in the signature. The data cannot be changed without rendering the transaction ID invalid.
The dataRefs
object should be located in the extensions
field of the miner info document.
"extensions": {
"dataRefs": {
"refs": [
{
"brfcIds": string[],
"txid": string,
"vout": number,
"compress": string
},
{
"brfcIds": string[],
"txid": string,
"vout": number,
"compress": string
}
]
}
}
field | description |
---|---|
dataRefs |
Extension name |
refs |
Array of reference objects with fields: brfcIds , txid , vout , and compress (optional) that each refer to a specific transaction output (TXO) |
field | description |
---|---|
brfcIds |
An array of BRFC ID strings indicating which extensions have data in the remote reference. This can be used to decide if the data is interesting to the user or not. |
txid |
Transaction ID of the transaction containing additional miner info document data. |
vout |
Vout index of the output containing additional miner info document data. |
compress (optional) |
If present, specifies a compression algorithm used to uncompress the target data blob. gzip is specified initially. |
"extensions": {
"dataRefs": {
"refs": [
{
"brfcIds": ["62b21572ca46", "a224052ad433"],
"txid": "c6e68a930db53b804b6cbc51d4582856079ce075cc305975f7d8f95755068267",
"vout": 2,
"compress": "gzip"
},
{
"brfcIds": ["b8930c2bbf5d", "1b1d980b5b72"],
"txid": "1bc783a5f7a0e5ef2016caf52cfeabb4b1f43039d57bc07144a5de12382deaf5",
"vout": 0,
"compress": "gzip"
}
]
}
}
The transaction output referenced by the txid
and vout
fields of each refs
object in the miner info documents should contain an output script at index 0. If there is more than one referenced output script to include, then each of them must be placed separately in the next consecutive output.
The format of the referenced output script is:
OP_0 OP_RETURN 0x601dface protocol-id-version OP_PUSHDATA json
field | description |
---|---|
json |
The brfcId field name should conform to BRFC ID Assignment. If the dataRef specifies a compress field this data may be compressed.Example: { "brfcId1": { ... }, ... } |
"extensions": {
"dataRefs": {
"refs": [{
"brfcIds": ["62b21572ca46", "a224052ad433"],
"txid": "c6e68a930db53b804b6cbc51d4582856079ce075cc305975f7d8f95755068267",
"vout": 2,
"compress": "gzip"
},
{
"brfcIds": ["b8930c2bbf5d", "1b1d980b5b72"],
"txid": "1bc783a5f7a0e5ef2016caf52cfeabb4b1f43039d57bc07144a5de12382deaf5",
"vout": 0,
"compress": "gzip"
}
],
"data": {
"62b21572ca46": {
// data for BRFC: 62b21572ca46
},
"a224052ad433": {
// data for BRFC: a224052ad433
},
"b8930c2bbf5d": {
// data for BRFC: b8930c2bbf5d
},
"1b1d980b5b72": {
// data for BRFC: 1b1d980b5b72
}
}
}
}
Note: The
"data"
section contains extension data that are defined in the referred to TXOs.
P2P messages sendhdrsen / gethdrsen / hdrsen
npm install
npm start
version | description |
---|---|
0.1 | Initial specification. |
0.2 | Change encoding of prevMinerIdSig (use hex encoding instead of default utf8). |
1.0 | Replace the VCTX transaction by the Revocation Keys. Static and dynamic coinbase documents replaced with miner info document. Coinbase transaction now contains a reference to the miner info document rather than containing the miner info document. Protocol specifier updated. |