Created
December 18, 2025 16:43
-
-
Save Timonchegs/a76d2eb2f65ad1a55211d4281b39eb14 to your computer and use it in GitHub Desktop.
last test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const net = require('net'); | |
| const https = require('https'); | |
| class AbelianStratumProxy { | |
| constructor() { | |
| this.currentJob = null; | |
| // Конфигурация из логов пула | |
| this.difficulty = 0.5; | |
| this.target = '00000001ffff0000000000000000000000000000000000000000000000000000'; // Для diff 0.5 | |
| this.algo = 'abelhash'; | |
| this.epoch = '100'; // Будет обновляться из ноды | |
| this.extranonce = '0'; | |
| this.extra_nonce_bits_num = '16'; | |
| } | |
| async rpcRequest(method, params = ['']) { | |
| return new Promise((resolve) => { | |
| const postData = JSON.stringify({ | |
| jsonrpc: '1.0', | |
| id: 'proxy', | |
| method: method, | |
| params: params | |
| }); | |
| const auth = Buffer.from('tteFTlJ7YOfGDA2KBMHKqnDnXeE=:SOkvF8sxay8ViOxpgbraHmqJmSU=').toString('base64'); | |
| const options = { | |
| hostname: '127.0.0.1', | |
| port: 8667, | |
| path: '/', | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': `Basic ${auth}`, | |
| 'Content-Length': Buffer.byteLength(postData) | |
| }, | |
| rejectUnauthorized: false | |
| }; | |
| const req = https.request(options, (res) => { | |
| let data = ''; | |
| res.on('data', chunk => data += chunk); | |
| res.on('end', () => { | |
| try { | |
| const parsed = JSON.parse(data); | |
| resolve(parsed.result); | |
| } catch (e) { | |
| console.error('RPC Parse Error:', e.message); | |
| resolve(null); | |
| } | |
| }); | |
| }); | |
| req.on('error', (error) => { | |
| console.error('RPC Request Error:', error.message); | |
| resolve(null); | |
| }); | |
| req.write(postData); | |
| req.end(); | |
| }); | |
| } | |
| async getWork() { | |
| console.log('[PROXY] Requesting work from node...'); | |
| const work = await this.rpcRequest('getwork', ['']); | |
| if (work && work.jobid) { | |
| this.currentJob = work; | |
| // Обновляем параметры из ответа ноды | |
| this.epoch = work.epoch?.toString() || '100'; | |
| this.extranonce = work.extranonce?.toString() || '0'; | |
| this.extra_nonce_bits_num = work.extranoncebitsnum?.toString() || '16'; | |
| console.log(`[PROXY] Work received: ${work.jobid.substring(0, 16)}...`); | |
| return true; | |
| } | |
| console.log('[PROXY] Failed to get work'); | |
| return false; | |
| } | |
| handleMinerConnection(socket) { | |
| const clientId = `${socket.remoteAddress}:${socket.remotePort}`; | |
| console.log(`[PROXY] New connection: ${clientId}`); | |
| const send = (data) => { | |
| if (socket.writable) { | |
| const str = JSON.stringify(data); | |
| console.log(`[PROXY -> MINER] ${str.substring(0, 100)}...`); | |
| socket.write(str + '\n'); | |
| } | |
| }; | |
| socket.on('data', async (data) => { | |
| const str = data.toString().trim(); | |
| console.log(`[MINER -> PROXY] ${str}`); | |
| try { | |
| const msg = JSON.parse(str); | |
| // 1. Ответ на mining.hello | |
| if (msg.method === 'mining.hello') { | |
| console.log(`[PROXY] Hello from: ${msg.params[0]}`); | |
| send({ | |
| id: msg.id, | |
| result: { | |
| proto: "AbelianStratum", | |
| encoding: "plain", | |
| resume: "0", | |
| timeout: "258", | |
| maxerrors: "10", | |
| node: "Abec-v2.0.2/Proxy-v1.0" | |
| }, | |
| error: null | |
| }); | |
| } | |
| // 2. Ответ на mining.subscribe | |
| else if (msg.method === 'mining.subscribe') { | |
| console.log('[PROXY] Subscribe'); | |
| send({ | |
| id: msg.id, | |
| result: [ | |
| ["mining.set_difficulty", "mining.set"], // Обрати внимание: mining.set, а не notify | |
| "08089999", | |
| 4 | |
| ], | |
| error: null | |
| }); | |
| } | |
| // 3. Ответ на mining.authorize | |
| else if (msg.method === 'mining.authorize') { | |
| console.log(`[PROXY] Authorize: ${msg.params[0]}`); | |
| send({ | |
| id: msg.id, | |
| result: { | |
| session_id: `s-${Date.now()}` | |
| }, | |
| error: null | |
| }); | |
| // 3.1 Отправляем результат авторизации (как в логах пула) | |
| setTimeout(() => { | |
| send({ | |
| id: null, | |
| result: { | |
| worker: msg.params[0].split('.')[0], // Кошелек без воркера | |
| registered: "0" | |
| }, | |
| error: null | |
| }); | |
| }, 50); | |
| // 3.2 Устанавливаем сложность | |
| setTimeout(() => { | |
| send({ | |
| id: null, | |
| method: "mining.set_difficulty", | |
| params: [this.difficulty] | |
| }); | |
| console.log(`[PROXY] Set difficulty: ${this.difficulty}`); | |
| }, 100); | |
| // 3.3 ОТПРАВЛЯЕМ РАБОТУ в формате mining.set (КАК НА ОФИЦИАЛЬНОМ ПУЛЕ) | |
| setTimeout(async () => { | |
| if (!this.currentJob) await this.getWork(); | |
| if (this.currentJob) { | |
| console.log('[PROXY] Sending work (mining.set)...'); | |
| // Ключевой момент: формат как в логах официального пула | |
| send({ | |
| method: "mining.set", | |
| params: { | |
| epoch: this.epoch, | |
| target: this.target, | |
| algo: this.algo, | |
| extranonce: this.extranonce, | |
| extra_nonce_bits_num: this.extra_nonce_bits_num | |
| }, | |
| id: null | |
| }); | |
| console.log(`[PROXY] Job sent. Epoch: ${this.epoch}, Target: ${this.target.substring(0, 16)}...`); | |
| } | |
| }, 150); | |
| } | |
| // 4. Ответ на mining.noop | |
| else if (msg.method === 'mining.noop') { | |
| console.log('[PROXY] Noop received'); | |
| send({ | |
| id: msg.id, | |
| result: true, | |
| error: null | |
| }); | |
| } | |
| } catch (e) { | |
| console.error(`[PROXY] JSON Parse Error: ${e.message}`); | |
| } | |
| }); | |
| socket.on('close', () => { | |
| console.log(`[PROXY] Connection closed: ${clientId}`); | |
| }); | |
| } | |
| async start(port = 3333) { | |
| console.log('[PROXY] Starting Abelian Stratum Proxy...'); | |
| console.log(`[PROXY] Target difficulty: ${this.difficulty}`); | |
| console.log(`[PROXY] Algorithm: ${this.algo}`); | |
| await this.getWork(); | |
| const server = net.createServer((socket) => { | |
| this.handleMinerConnection(socket); | |
| }); | |
| server.listen(port, '0.0.0.0', () => { | |
| console.log(`[PROXY] Listening on 0.0.0.0:${port}`); | |
| console.log('[PROXY] Ready for connections.'); | |
| }); | |
| } | |
| } | |
| const proxy = new AbelianStratumProxy(); | |
| proxy.start().catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment