Skip to content

Commit 1549f71

Browse files
author
Alexander Blair
committed
Update with AEON support.
1 parent 70b8cdf commit 1549f71

File tree

1 file changed

+248
-0
lines changed

1 file changed

+248
-0
lines changed

lib/aeon.js

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
"use strict";
2+
const multiHashing = require('multi-hashing');
3+
const cnUtil = require('cryptonote-util');
4+
const bignum = require('bignum');
5+
const support = require('./support.js')();
6+
const crypto = require('crypto');
7+
8+
let debug = {
9+
pool: require('debug')('pool'),
10+
diff: require('debug')('diff'),
11+
blocks: require('debug')('blocks'),
12+
shares: require('debug')('shares'),
13+
miners: require('debug')('miners'),
14+
workers: require('debug')('workers')
15+
};
16+
17+
let baseDiff = bignum('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16);
18+
19+
Buffer.prototype.toByteArray = function () {
20+
return Array.prototype.slice.call(this, 0);
21+
};
22+
23+
function blockHeightCheck(nodeList, callback) {
24+
let randomNode = nodeList[Math.floor(Math.random() * nodeList.length)].split(':');
25+
26+
}
27+
28+
function getRemoteNodes() {
29+
let knownNodes = [
30+
'162.213.38.245:18081',
31+
'116.93.119.79:18081',
32+
'85.204.96.231:18081',
33+
'107.167.87.242:18081',
34+
'107.167.93.58:18081',
35+
'199.231.85.122:18081',
36+
'192.110.160.146:18081'
37+
]; // Prefill the array with known good nodes for now. Eventually will try to download them via DNS or http.
38+
}
39+
40+
function BlockTemplate(template) {
41+
/*
42+
We receive something identical to the result portions of the monero GBT call.
43+
Functionally, this could act as a very light-weight solo pool, so we'll prep it as one.
44+
You know. Just in case amirite?
45+
*/
46+
this.id = template.id;
47+
this.blob = template.blocktemplate_blob;
48+
this.difficulty = template.difficulty;
49+
this.height = template.height;
50+
this.reservedOffset = template.reserved_offset;
51+
this.workerOffset = template.worker_offset; // clientNonceLocation
52+
this.targetDiff = template.target_diff;
53+
this.targetHex = template.target_diff_hex;
54+
this.buffer = new Buffer(this.blob, 'hex');
55+
this.previousHash = new Buffer(32);
56+
this.workerNonce = 0;
57+
this.solo = false;
58+
if (typeof(this.workerOffset) === 'undefined') {
59+
this.solo = true;
60+
global.instanceId.copy(this.buffer, this.reservedOffset + 4, 0, 3);
61+
this.buffer.copy(this.previousHash, 0, 7, 39);
62+
}
63+
this.nextBlob = function () {
64+
if (this.solo) {
65+
// This is running in solo mode.
66+
this.buffer.writeUInt32BE(++this.workerNonce, this.reservedOffset);
67+
} else {
68+
this.buffer.writeUInt32BE(++this.workerNonce, this.workerOffset);
69+
}
70+
return cnUtil.convert_blob(this.buffer).toString('hex');
71+
};
72+
}
73+
74+
function MasterBlockTemplate(template) {
75+
/*
76+
We receive something identical to the result portions of the monero GBT call.
77+
Functionally, this could act as a very light-weight solo pool, so we'll prep it as one.
78+
You know. Just in case amirite?
79+
*/
80+
this.blob = template.blocktemplate_blob;
81+
this.difficulty = template.difficulty;
82+
this.height = template.height;
83+
this.reservedOffset = template.reserved_offset; // reserveOffset
84+
this.workerOffset = template.client_nonce_offset; // clientNonceLocation
85+
this.poolOffset = template.client_pool_offset; // clientPoolLocation
86+
this.targetDiff = template.target_diff;
87+
this.targetHex = template.target_diff_hex;
88+
this.buffer = new Buffer(this.blob, 'hex');
89+
this.previousHash = new Buffer(32);
90+
this.job_id = template.job_id;
91+
this.workerNonce = 0;
92+
this.poolNonce = 0;
93+
this.solo = false;
94+
if (typeof(this.workerOffset) === 'undefined') {
95+
this.solo = true;
96+
global.instanceId.copy(this.buffer, this.reservedOffset + 4, 0, 3);
97+
this.buffer.copy(this.previousHash, 0, 7, 39);
98+
}
99+
this.blobForWorker = function () {
100+
this.buffer.writeUInt32BE(++this.poolNonce, this.poolOffset);
101+
return this.buffer.toString('hex');
102+
};
103+
}
104+
105+
function getJob(miner, activeBlockTemplate, bashCache) {
106+
if (miner.validJobs.size() >0 && miner.validJobs.get(0).templateID === activeBlockTemplate.id && !miner.newDiff && miner.cachedJob !== null && typeof bashCache === 'undefined') {
107+
return miner.cachedJob;
108+
}
109+
110+
let blob = activeBlockTemplate.nextBlob();
111+
let target = getTargetHex(miner);
112+
miner.lastBlockHeight = activeBlockTemplate.height;
113+
114+
let newJob = {
115+
id: crypto.pseudoRandomBytes(21).toString('base64'),
116+
extraNonce: activeBlockTemplate.workerNonce,
117+
height: activeBlockTemplate.height,
118+
difficulty: miner.difficulty,
119+
diffHex: miner.diffHex,
120+
submissions: [],
121+
templateID: activeBlockTemplate.id
122+
};
123+
124+
miner.validJobs.enq(newJob);
125+
miner.cachedJob = {
126+
blob: blob,
127+
job_id: newJob.id,
128+
target: target,
129+
id: miner.id
130+
};
131+
return miner.cachedJob;
132+
}
133+
134+
function getMasterJob(pool, workerID) {
135+
let activeBlockTemplate = pool.activeBlocktemplate;
136+
let btBlob = activeBlockTemplate.blobForWorker();
137+
let workerData = {
138+
id: crypto.pseudoRandomBytes(21).toString('base64'),
139+
blocktemplate_blob: btBlob,
140+
difficulty: activeBlockTemplate.difficulty,
141+
height: activeBlockTemplate.height,
142+
reserved_offset: activeBlockTemplate.reservedOffset,
143+
worker_offset: activeBlockTemplate.workerOffset,
144+
target_diff: activeBlockTemplate.targetDiff,
145+
target_diff_hex: activeBlockTemplate.targetHex
146+
};
147+
let localData = {
148+
id: workerData.id,
149+
masterJobID: activeBlockTemplate.job_id,
150+
poolNonce: activeBlockTemplate.poolNonce
151+
};
152+
if (!(workerID in pool.poolJobs)) {
153+
pool.poolJobs[workerID] = support.circularBuffer(4);
154+
}
155+
pool.poolJobs[workerID].enq(localData);
156+
return workerData;
157+
}
158+
159+
function getTargetHex(miner) {
160+
if (miner.newDiff) {
161+
miner.difficulty = miner.newDiff;
162+
miner.newDiff = null;
163+
}
164+
let padded = Buffer.alloc(32);
165+
let diffBuff = baseDiff.div(miner.difficulty).toBuffer();
166+
diffBuff.copy(padded, 32 - diffBuff.length);
167+
168+
let buff = padded.slice(0, 4);
169+
let buffArray = buff.toByteArray().reverse();
170+
let buffReversed = new Buffer(buffArray);
171+
miner.target = buffReversed.readUInt32BE(0);
172+
return buffReversed.toString('hex');
173+
}
174+
175+
function processShare(miner, job, blockTemplate, nonce, resultHash) {
176+
let template = new Buffer(blockTemplate.buffer.length);
177+
blockTemplate.buffer.copy(template);
178+
if (blockTemplate.solo) {
179+
template.writeUInt32BE(job.extraNonce, blockTemplate.reservedOffset);
180+
} else {
181+
template.writeUInt32BE(job.extraNonce, blockTemplate.workerOffset);
182+
}
183+
184+
let hash = new Buffer(resultHash, 'hex');
185+
let hashArray = hash.toByteArray().reverse();
186+
let hashNum = bignum.fromBuffer(new Buffer(hashArray));
187+
let hashDiff = baseDiff.div(hashNum);
188+
189+
if (hashDiff.ge(blockTemplate.targetDiff)) {
190+
// Validate share with CN hash, then if valid, blast it up to the master.
191+
let shareBuffer = cnUtil.construct_block_blob(template, new Buffer(nonce, 'hex'));
192+
let convertedBlob = cnUtil.convert_blob(shareBuffer);
193+
hash = multiHashing.cryptonight_light(convertedBlob);
194+
if (hash.toString('hex') !== resultHash) {
195+
console.error(global.threadName + "Bad share from miner " + miner.logString);
196+
miner.messageSender('job', miner.getJob(miner, blockTemplate, true));
197+
return false;
198+
}
199+
miner.blocks += 1;
200+
process.send({
201+
type: 'shareFind',
202+
host: miner.pool,
203+
data: {
204+
btID: blockTemplate.id,
205+
nonce: nonce,
206+
resultHash: resultHash,
207+
workerNonce: job.extraNonce
208+
}
209+
});
210+
}
211+
else if (hashDiff.lt(job.difficulty)) {
212+
process.send({type: 'invalidShare'});
213+
console.warn(global.threadName + "Rejected low diff share of " + hashDiff.toString() + " from: " + miner.address + " ID: " +
214+
miner.identifier + " IP: " + miner.ipAddress);
215+
return false;
216+
}
217+
miner.shares += 1;
218+
miner.hashes += job.difficulty;
219+
return true;
220+
}
221+
222+
let devPool = {
223+
"hostname": "pool.aeonminingpool.com",
224+
"port": 3333,
225+
"ssl": false,
226+
"share": 0,
227+
"username": "WmtvM6SoYya4qzkoPB4wX7FACWcXyFPWAYzfz7CADECgKyBemAeb3dVb3QomHjRWwGS3VYzMJAnBXfUx5CfGLFZd1U7ssdXTu",
228+
"password": "proxy_donations",
229+
"keepAlive": true,
230+
"coin": "xmr",
231+
"default": false,
232+
"devPool": true
233+
};
234+
235+
module.exports = function () {
236+
return {
237+
devPool: devPool,
238+
hashSync: multiHashing.cryptonight_light,
239+
hashAsync: multiHashing.CNLAsync,
240+
blockHeightCheck: blockHeightCheck,
241+
getRemoteNodes: getRemoteNodes,
242+
BlockTemplate: BlockTemplate,
243+
getJob: getJob,
244+
processShare: processShare,
245+
MasterBlockTemplate: MasterBlockTemplate,
246+
getMasterJob: getMasterJob
247+
};
248+
};

0 commit comments

Comments
 (0)