Skip to content

Commit

Permalink
Initial Zcoin commit
Browse files Browse the repository at this point in the history
  • Loading branch information
JCThePants committed May 12, 2020
1 parent 6c6f7d8 commit 9486c6f
Show file tree
Hide file tree
Showing 15 changed files with 454 additions and 182 deletions.
88 changes: 83 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
ref-stratum
===========
ref-stratum-zcoin
=================

This Reference Stratum is a simple implementation used as a basis for testing, experimentation, and
demonstration purposes. It is not intended for production use.

This project has been developed and tested on [Node v10](https://nodejs.org/) and [Ubuntu 16.04](http://releases.ubuntu.com/16.04/)

## Install ##
__Dependencies__
```bash
Expand All @@ -15,9 +17,85 @@ npm config set //npm.pkg.github.com/:_authToken <PERSONAL_ACCESS_TOKEN>

__Download from Github__
```bash
git clone https://github.com/MintPond/ref-stratum
git clone https://github.com/MintPond/ref-stratum-zcoin

# install
cd ref-stratum
cd ref-stratum-zcoin
npm install
```
```

__Install in a Project__
```bash

npm config set @mintpond:registry https://npm.pkg.github.com/mintpond
npm config set //npm.pkg.github.com/:_authToken <PERSONAL_ACCESS_TOKEN>

npm install @mintpond/ref-stratum-zcoin --save
```

## Usage ##
The stratum can be used as a module in a pool:
```javascript
const Stratum = require('@mintpond/ref-stratum-zcoin').Stratum;

class MyStratum extends Stratum {
/* Override */
canAuthorizeWorker(client, callback) {
// implement your own logic
if (client.minerAddress === 'bad') {
// do not authorize worker
callback(null/*error*/, false/*isAuthorized*/);
}
else {
// authorize worker
callback(null/*error*/, true/*isAuthorized*/);
}
}
}

const stratum = new MyStratum({
coinbaseAddress: 'TC6qME2GhepR7656DgsR72pkQDmhfTDbtV', // address that receives block reward
blockBrand: '/@mintpond/ref-stratum/', // Branding string added to every block found
host: "0.0.0.0", // address the stratum will listen on
port: {
number: 3000, // port the stratum will listen on
diff: 1024 // stratum difficulty
},
rpc: {
host: '172.16.3.102', // Zcoin daemon RPC host
port: 17001, // Zcoin daemon RPC port
user: 'rpcuser', // Zcoin daemon RPC user
password: "x" // Zcoin daemon RPC password
},
jobUpdateInterval: 55, // Broadcast job updates every n seconds
blockPollIntervalMs: 250 // Check for new blocks every n milliseconds
});

stratum.on(Stratum.EVENT_SHARE_SUBMITTED, ev => {
console.log(ev.share);
});

stratum.init();
```

### Start Script ###
There is a start script (`start.js`) included which contains further
examples. It can also be run in order to get a Stratum going for test
purposes. You will need to open and modify the config inside before
running it.
```
> node start
```

## Areas of Interest ##
- [ClientReader](libs/class.ClientReader.js) - Handles messages received from a client.
- [ClientWriter](libs/class.ClientWriter.js) - Handles sending messages to a client.
- [Coinbase](libs/class.Coinbase.js) - Creates coinbase transaction and includes founder rewards.
- [Share](libs/class.Share.js) - Processes shares, validates proofs, creates blocks.
- [Socket](libs/class.Socket.js) - Handles binary BOS serialization and deserialization.
- [algorithm](libs/service.algorithm.js) - Contains MTP constants and hash verification.


## Resources ##
- [Zcoin](https://zcoin.io/) - The first cryptocurrency to implement the Merkle Tree Proof POW algorithm.
- [MintPond Mining Pool](https://mintpond.com) - Zcoin mining pool.
4 changes: 2 additions & 2 deletions config.example.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"coinbaseAddress": "mpN96WyD5Xb8q66aVsfd7P6P2WJDdqapKf",
"coinbaseAddress": "TC6qME2GhepR7656DgsR72pkQDmhfTDbtV",
"blockBrand": "/@mintpond/ref-stratum/",
"host": "0.0.0.0",
"port": {
"number": 3020,
"number": 3000,
"diff": 1024
},
"rpc": {
Expand Down
78 changes: 48 additions & 30 deletions libs/class.ClientReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const
precon = require('@mintpond/mint-precon'),
mu = require('@mintpond/mint-utils'),
buffers = require('@mintpond/mint-utils').buffers,
Share = require('./class.Share'),
StratumError = require('./class.StratumError');

Expand Down Expand Up @@ -184,29 +185,65 @@ class ClientReader {
}

if (!Array.isArray(message.params)) {
_._client.emit(Client.EVENT_MALFORMED_MESSAGE, { message: message });
_._client.disconnect('Malformed message: params is not an array');
return true/*isHandled*/;
}

const workerName = message.params[0];
if (!workerName || !mu.isString(workerName)) {
_._client.emit(Client.EVENT_MALFORMED_MESSAGE, { message: message });
const jobIdBuf = message.params[1];
const extraNonce2Buf = message.params[2];
const nTimeBuf = message.params[3];
const nonceBuf = message.params[4];
const mtpHashRootBuf = message.params[5];
const mtpBlockBuf = message.params[6];
const mtpProofBuf = message.params[7];

if (!Buffer.isBuffer(jobIdBuf)) {
_._client.disconnect('Malformed message: jobIdBuf is not a Buffer');
return true/*isHandled*/;
}

if (!Buffer.isBuffer(extraNonce2Buf)) {
_._client.disconnect('Malformed message: extraNonce2Buf is not a Buffer');
return true/*isHandled*/;
}

const jobIdHex = _._hex(message.params[1]);
const extraNonce2Hex = _._hex(message.params[2]);
const nTimeHex = _._hex(message.params[3]);
const nonceHex = _._hex(message.params[4]);
if (!Buffer.isBuffer(nTimeBuf)) {
_._client.disconnect('Malformed message: nTimeBuf is not a Buffer');
return true/*isHandled*/;
}

if (!Buffer.isBuffer(nonceBuf)) {
_._client.disconnect('Malformed message: nonceBuf is not a Buffer');
return true/*isHandled*/;
}

if (!Buffer.isBuffer(mtpHashRootBuf)) {
_._client.disconnect('Malformed message: mtpHashRootBuf is not a Buffer');
return true/*isHandled*/;
}

if (!Buffer.isBuffer(mtpBlockBuf)) {
_._client.disconnect('Malformed message: mtpBlockBuf is not a Buffer');
return true/*isHandled*/;
}

if (!Buffer.isBuffer(mtpProofBuf)) {
_._client.disconnect('Malformed message: mtpProofBuf is not a Buffer');
return true/*isHandled*/;
}

const share = new Share({
client: _._client,
stratum: _._stratum,
workerName: workerName,
jobIdHex: jobIdHex,
extraNonce2Hex: extraNonce2Hex,
nTimeHex: nTimeHex,
nonceHex: nonceHex
jobIdHex: buffers.leToHex(jobIdBuf),
extraNonce2Buf: extraNonce2Buf,
nTimeBuf: nTimeBuf,
nonceBuf: nonceBuf,
mtpHashRootBuf: mtpHashRootBuf,
mtpBlockBuf: mtpBlockBuf,
mtpProofBuf: mtpProofBuf
});

const isValid = share.validate();
Expand All @@ -221,25 +258,6 @@ class ClientReader {

return true/*isHandled*/;
}


_hex(val) {

let value;

if (mu.isString(val)) {

if (val.startsWith('0x'))
val = val.substr(2);

value = val.toLowerCase();
}
else {
value = '';
}

return value;
}
}

module.exports = ClientReader;
36 changes: 17 additions & 19 deletions libs/class.ClientWriter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
const
precon = require('@mintpond/mint-precon'),
mu = require('@mintpond/mint-utils'),
buffers = require('@mintpond/mint-utils').buffers,
algorithm = require('./service.algorithm'),
Job = require('./class.Job'),
StratumError = require('./class.StratumError');

Expand Down Expand Up @@ -52,18 +54,10 @@ class ClientWriter {
const replyId = args.replyId;
const subscriptionIdHex = _._client.subscriptionIdHex;
const extraNonce1Hex = _._client.extraNonce1Hex;
const extraNonce2Size = _._client.extraNonce2Size;

_._socket.send({
id: replyId,
result: [
[
['mining.set_difficulty', subscriptionIdHex],
['mining.notify', subscriptionIdHex]
],
extraNonce1Hex,
extraNonce2Size
],
result: [buffers.hexToLE(subscriptionIdHex), buffers.hexToLE(extraNonce1Hex)],
error: null
});
}
Expand All @@ -81,25 +75,29 @@ class ClientWriter {
const diff = args.diff;

if (mu.isNumber(diff)) {

const nDiff = diff / algorithm.multiplier;
const targetBuf = buffers.packUInt256LE(algorithm.diff1 / nDiff);

_._socket.send({
id: null,
method: 'mining.set_difficulty',
params: [diff]
method: 'mining.set_target',
params: [targetBuf]
});
}

_._socket.send({
id: null,
method: 'mining.notify',
params: [
/* 0 Job Id */ job.idHex,
/* 1 prevhash */ job.prevBlockId,
/* 2 coinb1 */ job.coinbase.coinbase1Buf.toString('hex'),
/* 3 coinb2 */ job.coinbase.coinbase2Buf.toString('hex'),
/* 4 merkle_branch */ job.merkleTree.branchHexArr,
/* 5 version */ job.versionHex,
/* 6 nbits (diff) */ job.bitsHex,
/* 7 ntime */ job.curTimeHex,
/* 0 Job Id */ buffers.hexToLE(job.idHex),
/* 1 prevhash */ buffers.hexToLE(job.prevBlockId),
/* 2 coinb1 */ job.coinbase.coinbase1Buf,
/* 3 coinb2 */ job.coinbase.coinbase2Buf,
/* 4 merkle_branch */ job.merkleTree.branchBufArr,
/* 5 version */ job.versionBuf,
/* 6 nbits (diff) */ job.bitsBuf,
/* 7 ntime */ job.curTimeBuf,
/* 8 clean_jobs */ cleanJobs
]
});
Expand Down
43 changes: 39 additions & 4 deletions libs/class.Coinbase.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const
Share = require('./class.Share');

const
EXTRANONCE_SIZE = 8,
EXTRANONCE_SIZE = 16,
BUFFER_U32_ZERO = buffers.packUInt32LE(0),
BUFFER_VAR_ONE = buffers.packVarInt(1),
BUFFER_32_MAX = Buffer.from('FFFFFFFF', 'hex'),
Expand Down Expand Up @@ -72,8 +72,8 @@ class Coinbase {
const coinbase2Buf = _.coinbase2Buf;
return Buffer.concat([
coinbase1Buf,
Buffer.from(share.extraNonce1Hex, 'hex'),
Buffer.from(share.extraNonce2Hex, 'hex'),
share.extraNonce1Buf,
share.extraNonce2Buf,
coinbase2Buf
]);
}
Expand Down Expand Up @@ -138,11 +138,46 @@ class Coinbase {
const outputTxsArr = [];
const blockTemplate = _._blockTemplate;
const poolAddressScript = scripts.makeAddressScript(_._coinbaseAddress)
const isTestnet = _._coinbaseAddress[0] === 'T';

let poolRewardSt = blockTemplate.coinbasevalue;

const feeRewardSt = Math.round(poolRewardSt * 0.0025);
poolRewardSt -= feeRewardSt;

_._txCount = 0;

_._addTransaction(outputTxsArr, poolRewardSt, poolAddressScript, true);
const founder1RewardSt = 50000000;
const founder2RewardSt = 50000000;
const founder3RewardSt = 50000000;
const founder4RewardSt = 150000000;
const founder5RewardSt = 50000000;

const founder1Script = scripts.makeAddressScript(
isTestnet ? 'TDk19wPKYq91i18qmY6U9FeTdTxwPeSveo' : 'aCAgTPgtYcA4EysU4UKC86EQd5cTtHtCcr');

const founder2Script = scripts.makeAddressScript(
isTestnet ? 'TWZZcDGkNixTAMtRBqzZkkMHbq1G6vUTk5' : 'aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD');

const founder3Script = scripts.makeAddressScript(
isTestnet ? 'TRZTFdNCKCKbLMQV8cZDkQN9Vwuuq4gDzT' : 'aQ18FBVFtnueucZKeVg4srhmzbpAeb1KoN');

const founder4Script = scripts.makeAddressScript(
isTestnet ? 'TG2ruj59E5b1u9G3F7HQVs6pCcVDBxrQve' : 'a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3');

const founder5Script = scripts.makeAddressScript(
isTestnet ? 'TCsTzQZKVn4fao8jDmB9zQBk9YQNEZ3XfS' : 'a1kCCGddf5pMXSipLVD9hBG2MGGVNaJ15U');

const feeScript = scripts.makeAddressScript(
isTestnet ? 'TC6qME2GhepR7656DgsR72pkQDmhfTDbtV' : 'aMaQErBviQDyXBPuh4cq6FBCnXhpVWiXT4');

_._addTransaction(outputTxsArr, founder1RewardSt, founder1Script);
_._addTransaction(outputTxsArr, founder2RewardSt, founder2Script);
_._addTransaction(outputTxsArr, founder3RewardSt, founder3Script);
_._addTransaction(outputTxsArr, founder4RewardSt, founder4Script);
_._addTransaction(outputTxsArr, founder5RewardSt, founder5Script);
_._addTransaction(outputTxsArr, feeRewardSt, feeScript);
_._addTransaction(outputTxsArr, poolRewardSt, poolAddressScript);

const default_witness_commitment = blockTemplate.default_witness_commitment;
if (default_witness_commitment) {
Expand Down
Loading

0 comments on commit 9486c6f

Please sign in to comment.