184 lines
5.5 KiB
JavaScript
184 lines
5.5 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Test Client for RIN Stratum Proxy
|
|
* This simulates a miner connecting to the stratum server
|
|
*/
|
|
|
|
const net = require('net');
|
|
const readline = require('readline');
|
|
|
|
class StratumTestClient {
|
|
constructor(host = '127.0.0.1', port = 3333) {
|
|
this.host = host;
|
|
this.port = port;
|
|
this.socket = null;
|
|
this.messageId = 1;
|
|
this.subscribed = false;
|
|
this.authorized = false;
|
|
this.currentJob = null;
|
|
|
|
console.log('🧪 RIN Stratum Test Client');
|
|
console.log(`🔗 Connecting to ${host}:${port}`);
|
|
}
|
|
|
|
connect() {
|
|
return new Promise((resolve, reject) => {
|
|
this.socket = new net.Socket();
|
|
|
|
this.socket.connect(this.port, this.host, () => {
|
|
console.log('✅ Connected to stratum server');
|
|
resolve();
|
|
});
|
|
|
|
this.socket.on('data', (data) => {
|
|
this.handleMessage(data.toString());
|
|
});
|
|
|
|
this.socket.on('close', () => {
|
|
console.log('🔌 Connection closed');
|
|
});
|
|
|
|
this.socket.on('error', (error) => {
|
|
console.error(`❌ Connection error: ${error.message}`);
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
|
|
handleMessage(message) {
|
|
try {
|
|
const lines = message.trim().split('\n');
|
|
for (const line of lines) {
|
|
if (line) {
|
|
const data = JSON.parse(line);
|
|
console.log('📨 Received:', JSON.stringify(data, null, 2));
|
|
|
|
if (data.method === 'mining.notify') {
|
|
this.handleMiningNotify(data.params);
|
|
} else if (data.method === 'mining.set_difficulty') {
|
|
this.handleSetDifficulty(data.params);
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(`❌ Message parsing error: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
handleMiningNotify(params) {
|
|
if (params.length >= 8) {
|
|
this.currentJob = {
|
|
jobId: params[0],
|
|
prevhash: params[1],
|
|
coinb1: params[2],
|
|
coinb2: params[3],
|
|
merkleBranch: params[4],
|
|
version: params[5],
|
|
bits: params[6],
|
|
ntime: params[7],
|
|
cleanJobs: params[8]
|
|
};
|
|
|
|
console.log(`🆕 New job received: ${this.currentJob.jobId}`);
|
|
console.log(` Height: ${this.currentJob.version} | Bits: ${this.currentJob.bits}`);
|
|
|
|
// Simulate mining by submitting a test share
|
|
setTimeout(() => {
|
|
this.submitTestShare();
|
|
}, 1000);
|
|
}
|
|
}
|
|
|
|
handleSetDifficulty(params) {
|
|
if (params.length > 0) {
|
|
console.log(`🎯 Difficulty set to: ${params[0]}`);
|
|
}
|
|
}
|
|
|
|
sendMessage(method, params = [], id = null) {
|
|
const message = {
|
|
id: id || this.messageId++,
|
|
method: method,
|
|
params: params
|
|
};
|
|
|
|
const jsonMessage = JSON.stringify(message) + '\n';
|
|
console.log('📤 Sending:', JSON.stringify(message, null, 2));
|
|
this.socket.write(jsonMessage);
|
|
}
|
|
|
|
async subscribe() {
|
|
console.log('📝 Subscribing to stratum server...');
|
|
this.sendMessage('mining.subscribe', ['TestMiner/1.0']);
|
|
this.subscribed = true;
|
|
}
|
|
|
|
async authorize(username = 'testworker', password = 'x') {
|
|
console.log(`🔐 Authorizing as ${username}...`);
|
|
this.sendMessage('mining.authorize', [username, password]);
|
|
this.authorized = true;
|
|
}
|
|
|
|
submitTestShare() {
|
|
if (!this.currentJob) {
|
|
console.log('❌ No current job to submit share for');
|
|
return;
|
|
}
|
|
|
|
console.log('📊 Submitting test share...');
|
|
|
|
// Generate test values
|
|
const extranonce2 = Math.floor(Math.random() * 0xffffffff).toString(16).padStart(8, '0');
|
|
const ntime = this.currentJob.ntime;
|
|
const nonce = Math.floor(Math.random() * 0xffffffff).toString(16).padStart(8, '0');
|
|
|
|
this.sendMessage('mining.submit', [
|
|
'testworker',
|
|
this.currentJob.jobId,
|
|
extranonce2,
|
|
ntime,
|
|
nonce
|
|
]);
|
|
}
|
|
|
|
async run() {
|
|
try {
|
|
await this.connect();
|
|
await this.subscribe();
|
|
|
|
// Wait a bit for subscription response
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
await this.authorize();
|
|
|
|
// Keep connection alive
|
|
console.log('🔄 Test client running. Press Ctrl+C to exit.');
|
|
|
|
// Simulate periodic share submissions
|
|
setInterval(() => {
|
|
if (this.currentJob && this.authorized) {
|
|
this.submitTestShare();
|
|
}
|
|
}, 5000);
|
|
|
|
} catch (error) {
|
|
console.error(`❌ Test client error: ${error.message}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle graceful shutdown
|
|
process.on('SIGINT', () => {
|
|
console.log('\n🛑 Shutting down test client...');
|
|
process.exit(0);
|
|
});
|
|
|
|
// Start test client
|
|
const client = new StratumTestClient();
|
|
client.run().catch(error => {
|
|
console.error(`❌ Failed to start test client: ${error.message}`);
|
|
process.exit(1);
|
|
});
|