Skip to content

Commit 5e7bdc7

Browse files
committed
Initial commit
0 parents  commit 5e7bdc7

11 files changed

+3725
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.DS_Store
2+
.history
3+
.vscode
4+
/node_modules

LICENSE

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
Open BSV License
2+
Copyright (c) 2019 Bitcoin Association
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
1 - The above copyright notice and this permission notice shall be included in
12+
all copies or substantial portions of the Software.
13+
2 - The Software, and any software that is derived from the Software or parts thereof,
14+
can only be used on the Bitcoin SV blockchains. The Bitcoin SV blockchains are defined,
15+
for purposes of this license, as the Bitcoin blockchain containing block height #556767
16+
with the hash "000000000000000001d956714215d96ffc00e0afda4cd0a96c96f8d802b1662b" and
17+
the test blockchains that are supported by the un-modified Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
28+
29+
Version 0.1.1 of the Bitcoin SV software, and prior versions of software upon which it was based,
30+
were licensed under the MIT License, which is included below.
31+
32+
The MIT License (MIT)
33+
34+
Copyright (c) 2009-2010 Satoshi Nakamoto
35+
Copyright (c) 2009-2015 Bitcoin Developers
36+
Copyright (c) 2009-2017 The Bitcoin Core developers
37+
Copyright (c) 2017 The Bitcoin ABC developers
38+
Copyright (c) 2018 Bitcoin Association
39+
40+
Permission is hereby granted, free of charge, to any person obtaining a copy
41+
of this software and associated documentation files (the "Software"), to deal
42+
in the Software without restriction, including without limitation the rights
43+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
44+
copies of the Software, and to permit persons to whom the Software is
45+
furnished to do so, subject to the following conditions:
46+
47+
The above copyright notice and this permission notice shall be included in
48+
all copies or substantial portions of the Software.
49+
50+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
53+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
54+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
55+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
56+
THE SOFTWARE.

README.md

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# MinerId Builder - Reference Implementation
2+
3+
More details available in the [BRFC Spec](https://bitbucket.org/nchteamnch/minerid/src/master/) for MinerId.
4+
5+
6+
## Configuration
7+
8+
[config.json](config.json) options:
9+
10+
- change port
11+
- change minerIdDataPath which stores user's minerids
12+
- change keystore which stores minerId private keys
13+
- change network (mainnet="livenet" | testnet="testnet" | regtest="regtest")
14+
- change Bitcoin RPC parameters
15+
16+
## Installation
17+
18+
```console
19+
$ npm install
20+
```
21+
22+
To run API server:
23+
```
24+
$ npm start
25+
```
26+
27+
To run CLI:
28+
```
29+
$ npm run cli
30+
```
31+
32+
## CLI
33+
34+
### Options
35+
36+
`--command string[] generatevctx, rotateid, config`
37+
38+
`-h, --help Display this usage guide.`
39+
40+
`-t, --height number The block height that will be included in the coinbase document.`
41+
42+
`-n, --name string The alias for the minerId. This shouldn't change while the minerId may be changed by rotating it.`
43+
44+
45+
### Examples
46+
47+
Generate a new minerId. This will generate a minerId and associate it with the alias name
48+
49+
`npm run cli -- generateminerid --name foo`
50+
or
51+
`npm run cli -- generateminerid -n foo`
52+
53+
Generate a Validity Check Transaction (VCTX).
54+
55+
`npm run cli -- generatevctx --name foo`
56+
57+
Generate op_return with signed coinbase document.
58+
59+
`npm run cli -- --height 5123123 --name foo`
60+
61+
Rotate a minerId. This command rotates the minerId which generates a new one. This is done by spending the current VCTX to create a new VCTX with the new minerId in op_return. Subsequent coinbase documents will contain references to both minerIds
62+
63+
`npm run cli -- rotateminerid --name foo`
64+
65+
Add a key value pair to the config file. This will be used to fill the `minerContact` object. You can add any key value pairs here but you should add one called `name` as this can then be used to identify you. Obviously this doesn't have to be your real name but should be something you're happy to share with the world.
66+
67+
`npm run cli -- config [email protected] -n foo`
68+
or
69+
`npm run cli -- config website=foo.com -n foo`
70+
71+
## API
72+
73+
## Implementation
74+
75+
The **REST API** has 4 endpoints:
76+
77+
### 1. `GET /opreturn/:alias/:blockHeight([0-9]+)`
78+
79+
`alias`: MinerId alias
80+
`blockHeight`: block height which MinerId document is created for/at
81+
82+
**returns** MinerId output (locking) script hex string for an `alias` MinerId at height `blockHeight`
83+
84+
#### Example
85+
86+
```console
87+
$ curl localhost:9002/opreturn/testMiner/1234
88+
89+
006a04ac1eed884de1017b2276657273696f6e223a22302e31222c22686569676874223a313233342c22707265764d696e65724964223a22303364383139363262316561373964306530366438653166363661323661363064346561636463323430373236326332393130633537303963613937613637623864222c22707265764d696e65724964536967223a223330343430323230313131636338383437663638636334636333346335363863376533396635333965663161663832616563613765376565633766646330653230663439393938623032323031653232376437656334623163643138626637656631323463303661653135376232623136363835313934303536623834633836616563333961643731663139222c226d696e65724964223a22303364383139363262316561373964306530366438653166363661323661363064346561636463323430373236326332393130633537303963613937613637623864222c2276637478223a7b2274784964223a2236653631363431643034613463336337353164363536663938666238343533383738376565343335393830626432323865616163386534663364646162643033222c22766f7574223a307d2c226d696e6572436f6e74616374223a7b226e616d65223a22746573744d696e6572227d7d4630440220509d60519d1508045b4629bfb748fc6d9c7e240bc6cea49d5ec084c818005e2c022069ebd520bf65b75b9bd579b7ae09559efe2b6857e64cc47ae6700aa2e6e8132e
90+
```
91+
92+
### 2. `GET /opreturn/:alias/rotate`
93+
94+
`alias`: MinerId alias
95+
96+
rotates the MinerId key for an `alias` MinerId
97+
98+
#### Example
99+
100+
```console
101+
$ curl localhost:9002/opreturn/testMiner/rotate
102+
103+
OK
104+
```
105+
106+
### 3. `GET /minerid/:alias`
107+
108+
`alias`: MinerId alias
109+
110+
**returns** compressed public key (33 byte) hex string for an `alias` MinerId
111+
112+
#### Example
113+
114+
```console
115+
$ curl localhost:9002/minerid/testMiner
116+
117+
02644f5000535bbc135f9c8613f86f10c66a4a773eda5e913eff64eb328bc6326a
118+
```
119+
120+
121+
### 4. `GET /minerid/:alias/sign/:hash`
122+
123+
`alias`: MinerId alias
124+
`hash`: SHA256 hash (32 byte hex string) to be fed to ECDSA signing agorithm
125+
126+
127+
**returns** hash signature (71-73 byte hex string) using an `alias` MinerId
128+
129+
#### Example
130+
131+
```console
132+
$ curl localhost:9002/minerid/testMiner/sign/02644f5000535bbc135f9c8613f86f10c66a4a773eda5e913eff64eb328bc632
133+
134+
3045022100e0f86a5b1748ae48b0d10ea305202769d754071272cba0fbb82f74f8e8da8b530220494351742f3ba9e51b155df15b13f27c927d21956822aedcbb7d179c66d4d4c0
135+
```
136+
137+
138+
## Example Miner Code
139+
140+
[testMiner.js](testMiner.js) contains basic code needed to generate a coinbase transaction that has a MinerId (ouput) in it by calling the first API [endpoint](#1-get-opreturnaliasblockheight0-9) and then adding that ouput to it's coinbase transaction.
141+
142+
1. Generate MinerId
143+
` npm run cli -- generateminerid -n testMiner`
144+
145+
2. Generate VcTx (not needed for Regtest)
146+
`npm run cli -- generatevctx -n testMiner`
147+
148+
3. Create coinbase transaction
149+
`node examples/testMiner.js`

builder.js

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
const express = require('express')
2+
const config = require('./config.json')
3+
const fm = require('./utils/filemanager')
4+
5+
const coinbaseDocService = require('./services/coinbaseDocumentService')
6+
7+
const app = express()
8+
9+
app.get('/opreturn/:alias/:blockHeight([0-9]+)', async (req, res) => {
10+
res.setHeader('Content-Type', 'text/plain')
11+
12+
if (!fm.aliasExists(req.params.alias)) {
13+
res.status(400).send(`Alias "${req.params.alias}" doesn't exist`)
14+
return
15+
}
16+
17+
try {
18+
const opReturn = await coinbaseDocService.createMinerIdOpReturn(req.params.blockHeight, req.params.alias)
19+
res.send(opReturn)
20+
} catch (err) {
21+
res.status(500).send(`Internal error ${err.message}`)
22+
}
23+
})
24+
25+
app.get('/opreturn/:alias/rotate', (req, res) => {
26+
res.setHeader('Content-Type', 'text/plain')
27+
28+
if (!fm.aliasExists(req.params.alias)) {
29+
res.status(400).send(`Alias "${req.params.alias}" doesn't exist`)
30+
return
31+
}
32+
33+
try {
34+
coinbaseDocService.rotateMinerId(req.params.alias)
35+
res.send('OK')
36+
} catch (err) {
37+
res.status(500).send(`Internal error ${err.message}`)
38+
}
39+
})
40+
41+
app.get('/minerid/:alias', (req, res) => {
42+
res.setHeader('Content-Type', 'text/plain')
43+
44+
if (!fm.aliasExists(req.params.alias)) {
45+
res.status(400).send(`Alias "${req.params.alias}" doesn't exist`)
46+
return
47+
}
48+
49+
try {
50+
const currentAlias = coinbaseDocService.getCurrentMinerId(req.params.alias)
51+
res.send(currentAlias)
52+
} catch (err) {
53+
res.status(500).send(`Internal error ${err.message}`)
54+
}
55+
})
56+
57+
app.get('/minerid/:alias/sign/:hash([0-9a-fA-F]+)', (req, res) => {
58+
res.setHeader('Content-Type', 'text/plain')
59+
60+
if (!fm.aliasExists(req.params.alias)) {
61+
res.status(400).send(`Alias "${req.params.alias}" doesn't exist`)
62+
return
63+
}
64+
65+
if (req.params.hash.length !== 64) {
66+
res.status(400).send('Hash must be 64 characters (32 byte hex string)')
67+
return
68+
}
69+
70+
try {
71+
const signature = coinbaseDocService.signWithCurrentMinerId(req.params.hash, req.params.alias)
72+
res.send(signature)
73+
} catch (err) {
74+
res.status(500).send(`Internal error ${err.message}`)
75+
}
76+
})
77+
78+
app.listen(config.port, () => {
79+
console.log(`Server running on port ${config.port}`)
80+
})

0 commit comments

Comments
 (0)