ibctminer
Version:
```js const IntMiner = require('./src'); const Debug = require('./src/log')(); const fs = require('fs'); const COMP = '[SIPC]';
281 lines (257 loc) • 8.92 kB
JavaScript
const EventEmitter = require('events');
const stratum = require('./stratum');
const Debug = require('../log')();
const uuid = require("uuid");
const COMP = '[intStratum]';
class intStratum extends EventEmitter {
constructor({}) {
super();
var _this = this;
_this.client = null;
_this.online = false;
_this.auth = false;
_this.subinfo = null;
_this.subinfoturn = false;
_this.diffinfo = null;
_this.socket = null;
_this.sendQueue = [];
_this.user = null;
_this.pass = null;
_this.lastRecvPacket = null;
_this.lastSendPacket = null;
_this.id = uuid.v4();
return _this;
}
stratumAuthorize(id, user, pass) {
return this.socket.stratumSend({
'method': 'mining.authorize',
'id': id,
'params': [user, pass]
}, true);
}
stratumSubmit(id, submitData) {
this.socket.setLastActivity();
return this.socket.stratumSend({
'method': 'mining.submit',
'id': id,
'params': submitData
});
}
setupLoginPacket(data, job, diff, info) {
// for setup for connect.js
var packet = {
id: data.id,
error: null,
result: {
id: this.id,
job: job,
diff: diff,
subscribe: info,
}
};
return packet;
}
getPacketByID(id) {
var packet = null;
this.sendQueue = this.sendQueue.filter(function (pkt) {
if (pkt.id === id && !packet) {
packet = pkt;
return false;
} else {
return true;
}
});
return packet;
}
getPacketByMethod(method) {
var packet = null;
this.sendQueue = this.sendQueue.filter(function (pkt) {
if (pkt.method === method && !packet) {
packet = pkt;
return false;
} else {
return true;
}
});
return packet;
}
init(ssl, host, port) {
var _this = this;
if (_this.online) {
_this.kill();
return;
} else if (!_this.client) {
_this.client = stratum.Client.$create();
if (!_this.client) {
_this.emit('error', __('创建Stratum客户端失败'));
}
}
_this.client.on('error', function (socket, e) {
// xmr.viabtc.com donation pool
if (e.host !== 'xmr.viabtc.com') {
_this.emit("error", __('网络连接中断'));
}
});
_this.client.on('timeout', function (socket, e) {
// xmr.viabtc.com donation pool
if (socket.socket._host !== 'xmr.viabtc.com') {
_this.emit("error", __('Socket请求超时'));
}
});
_this.client.on('mining.error', function (msg, socket) {
Debug.IbctLogErr(COMP, msg);
_this.emit("error", __('Stratum连接中断'));
});
_this.client.connect({
host: host,
port: port
}).then(function (socket) {
Debug.IbctLogDbg(COMP, 'Connected! lets ask for subscribe');
if (!_this.online) {
_this.online = true;
}
_this.socket = socket;
_this.emit('connect');
})
}
kill() {
if (this.client) {
this.client.removeAllListeners();
if (this.client.destroy) {
this.client.destroy();
}
this.client = null;
}
if (this.sendQueue.length)
this.sendQueue.splice(0, this.sendQueue.length);
this.lastRecvPacket = null;
this.lastSendPacket = null;
if (this.online) {
this.online = false;
this.auth = false;
this.removeAllListeners();
}
}
getPacket() {
var _this = this;
var packet = null;
// TODO: have done in init
// the client is a one-way communication, it receives data from the server after issuing commands
_this.client.on('mining', function (data, socket, type) {
// type will be either 'broadcast' or 'result'
Debug.IbctLogInfo(COMP, '<===' + type + ' = ', JSON.stringify(data));
// you can issue more commands to the socket, it's the exact same socket as "client" variable
// in this example
// the socket (client) got some fields like:
// client.name = name of the worker
// client.authorized = if the current connection is authorized or not
// client.id = an UUID ([U]niversal [U]nique [ID]entifier) that you can safely rely on it's uniqueness
// client.subscription = the subscription data from the server
switch (data.method) {
case 'set_difficulty':
case 'mining.set_difficulty':
// server sent the new difficulty
Debug.IbctLogInfo(COMP, 'mining.set_difficulty');
if (!socket.authorized) {
_this.diffinfo = data;
} else {
_this.emit('data', _this.setupLoginPacket(data, null,data.params,null));
}
break;
case 'notify':
case 'mining.notify':
// server sent a new block
// Debug.IbctLogInfo(COMP, 'mining.notify');
if (!_this.auth) {
_this.lastRecvPacket = data.params;
} else {
_this.emit('data', _this.setupLoginPacket(data, data.params,null,null));
}
break;
default:
if (!socket.authorized) {
_this.subinfo = data;
Debug.IbctLogDbg(COMP, 'Asking for authorization');
if (_this.lastSendPacket && _this.lastSendPacket.method === 'login' && !_this.auth) {
Debug.IbctLogErr(COMP, 'Login failed: ', _this.user);
if (data.error && data.error.message)
_this.emit('error', __('矿池登陆失败') + ': ' + data.error.message);
else if (data.error && (data.error instanceof Array) && data.error.length > 2) {
_this.emit('error', __('矿池登陆失败') + ': ' + data.error[1])
} else
_this.emit('error', __('矿池登陆失败'));
return
}
packet = _this.getPacketByMethod('login');
if (packet) {
_this.lastSendPacket = packet;
Debug.IbctLogInfo(COMP, 'Login User: ', _this.user);
_this.stratumAuthorize(packet.id, packet.params.login, packet.params.pass);
}
} else {
if (!_this.lastSendPacket) {
return
}
/*add this step for 6 block */
if(_this.subinfoturn === true) {
_this.subinfo = data;
_this.subinfoturn = false;
}
if (_this.lastSendPacket.method === 'login' && !_this.auth) {
Debug.IbctLogDbg(COMP, 'We are authorized', _this.lastRecvPacket);
_this.emit('data', _this.setupLoginPacket(data, _this.lastRecvPacket, null, null));
_this.auth = true;
if(_this.subinfo.result === null){
_this.subinfoturn = true;
_this.socket.stratumSubscribe('icbtminer');
}
}
if(typeof _this.subinfo.result === 'object' && _this.subinfo.result !== null) {
_this.emit('data', _this.setupLoginPacket(_this.subinfo, null, null, _this.subinfo.result));
_this.subinfo.result = null;
}
if( _this.diffinfo !== null) {
_this.emit('data', _this.setupLoginPacket(_this.diffinfo, null, _this.diffinfo.params, null));
_this.diffinfo = null;
}
if (_this.lastSendPacket.method === 'submit') {
_this.emit('data', data);
}
}
}
});
}
sendPacket(message) {
var _this = this;
Debug.IbctLogInfo(COMP, 'sendPacket: ', JSON.stringify(message));
this.sendQueue.push(message);
if (message.method === 'login') {
this.user = message.params.login;
this.pass = message.params.pass;
// After the first stratumSubscribe, the data will be handled internally
// and returned deferreds to be resolved / rejected through the event 'mining'
// above
this.socket.stratumSubscribe('icbtminer').then(
// This isn't needed, it's handled automatically inside the Client class
// but if you want to deal with anything special after subscribing and such.
function (socket) {
Debug.IbctLogDbg(COMP, 'Sent!');
},
function (error) {
Debug.IbctLogErr(COMP, 'Error');
}
);
}
// have login
if (message.method === 'submit') {
_this.lastSendPacket = message;
return this.stratumSubmit(message.id, message.params.params.submit);
}
}
isWritable() {
return true;
}
};
module.exports = function GetIntStratum(options = {}) {
return new intStratum(options);
};