mirror of
https://github.com/benjamin-wilson/public-pool.git
synced 2026-09-29 09:05:06 -07:00
enable stratum TLS
This commit is contained in:
@@ -17,6 +17,9 @@ BITCOIN_RPC_TIMEOUT=10000
|
|||||||
API_PORT=3334
|
API_PORT=3334
|
||||||
STRATUM_PORTS=3333,3332,3331,3330
|
STRATUM_PORTS=3333,3332,3331,3330
|
||||||
|
|
||||||
|
STRATUM_SECURE=true
|
||||||
|
SECURE_STRATUM_PORTS=4333,4332,4331,4330
|
||||||
|
|
||||||
#optional telegram bot
|
#optional telegram bot
|
||||||
#TELEGRAM_BOT_TOKEN=
|
#TELEGRAM_BOT_TOKEN=
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ import { BitcoinRpcService } from './bitcoin-rpc.service';
|
|||||||
import { NotificationService } from './notification.service';
|
import { NotificationService } from './notification.service';
|
||||||
import { StratumV1JobsService } from './stratum-v1-jobs.service';
|
import { StratumV1JobsService } from './stratum-v1-jobs.service';
|
||||||
|
|
||||||
|
import { readFileSync } from 'fs';
|
||||||
|
import { TlsOptions, TLSSocket, createServer } from 'tls';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StratumV1Service implements OnModuleInit {
|
export class StratumV1Service implements OnModuleInit {
|
||||||
@@ -20,111 +25,187 @@ export class StratumV1Service implements OnModuleInit {
|
|||||||
private normalClosure = 0;
|
private normalClosure = 0;
|
||||||
private errorClosure = 0;
|
private errorClosure = 0;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly bitcoinRpcService: BitcoinRpcService,
|
private readonly bitcoinRpcService: BitcoinRpcService,
|
||||||
private readonly clientService: ClientService,
|
private readonly clientService: ClientService,
|
||||||
private readonly clientStatisticsService: ClientStatisticsService,
|
private readonly clientStatisticsService: ClientStatisticsService,
|
||||||
private readonly notificationService: NotificationService,
|
private readonly notificationService: NotificationService,
|
||||||
private readonly blocksService: BlocksService,
|
private readonly blocksService: BlocksService,
|
||||||
private readonly configService: ConfigService,
|
private readonly configService: ConfigService,
|
||||||
private readonly stratumV1JobsService: StratumV1JobsService,
|
private readonly stratumV1JobsService: StratumV1JobsService,
|
||||||
private readonly addressSettingsService: AddressSettingsService
|
private readonly addressSettingsService: AddressSettingsService
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
async onModuleInit(): Promise<void> {
|
|
||||||
|
|
||||||
if (process.env.MASTER == 'true') {
|
|
||||||
await this.clientService.deleteAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for all the other processes to init for an even connection distribution
|
async onModuleInit(): Promise<void> {
|
||||||
setTimeout(() => {
|
|
||||||
process.env.STRATUM_PORTS.split(',').forEach(port =>{
|
|
||||||
this.startSocketServer(parseInt(port));
|
|
||||||
});
|
|
||||||
}, (10000));
|
|
||||||
|
|
||||||
setInterval(() => {
|
if (process.env.MASTER == 'true') {
|
||||||
console.log(`Socket stats: ${this.emptySocket} empty, ${this.socketTimeout} timeouts, ${this.normalClosure} normal closure, ${this.errorClosure} error closure`);
|
await this.clientService.deleteAll();
|
||||||
this.emptySocket = 0;
|
}
|
||||||
this.socketTimeout = 0;
|
|
||||||
this.normalClosure = 0;
|
|
||||||
this.errorClosure = 0;
|
|
||||||
}, 1000 * 60);
|
|
||||||
|
|
||||||
}
|
// wait for all the other processes to init for an even connection distribution
|
||||||
|
setTimeout(() => {
|
||||||
|
process.env.STRATUM_PORTS.split(',').forEach(port => {
|
||||||
|
this.startSocketServer(parseInt(port));
|
||||||
|
});
|
||||||
|
if (process.env.STRATUM_SECURE?.toLowerCase() === 'true') {
|
||||||
|
process.env.SECURE_STRATUM_PORTS.split(',').forEach(port => {
|
||||||
|
this.startSecureSocketServer(parseInt(port));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, (10000));
|
||||||
|
|
||||||
private startSocketServer(port: number) {
|
setInterval(() => {
|
||||||
const server = new Server(async (socket: Socket) => {
|
console.log(`Socket stats: ${this.emptySocket} empty, ${this.socketTimeout} timeouts, ${this.normalClosure} normal closure, ${this.errorClosure} error closure`);
|
||||||
// Set 15-minute timeout
|
this.emptySocket = 0;
|
||||||
socket.setTimeout(1000 * 60 * 15);
|
this.socketTimeout = 0;
|
||||||
|
this.normalClosure = 0;
|
||||||
|
this.errorClosure = 0;
|
||||||
|
}, 1000 * 60);
|
||||||
|
|
||||||
const client = new StratumV1Client(
|
}
|
||||||
socket,
|
|
||||||
this.stratumV1JobsService,
|
|
||||||
this.bitcoinRpcService,
|
|
||||||
this.clientService,
|
|
||||||
this.clientStatisticsService,
|
|
||||||
this.notificationService,
|
|
||||||
this.blocksService,
|
|
||||||
this.configService,
|
|
||||||
this.addressSettingsService
|
|
||||||
);
|
|
||||||
|
|
||||||
// Unified cleanup function
|
private startSocketServer(port: number) {
|
||||||
const cleanup = async (reason: string) => {
|
const server = new Server(async (socket: Socket) => {
|
||||||
if (client.extraNonceAndSessionId != null) {
|
// Set 15-minute timeout
|
||||||
await client.destroy();
|
socket.setTimeout(1000 * 60 * 15);
|
||||||
if(reason == 'Error'){
|
|
||||||
this.errorClosure++;
|
const client = new StratumV1Client(
|
||||||
}else{
|
socket,
|
||||||
this.normalClosure++;
|
this.stratumV1JobsService,
|
||||||
|
this.bitcoinRpcService,
|
||||||
|
this.clientService,
|
||||||
|
this.clientStatisticsService,
|
||||||
|
this.notificationService,
|
||||||
|
this.blocksService,
|
||||||
|
this.configService,
|
||||||
|
this.addressSettingsService
|
||||||
|
);
|
||||||
|
|
||||||
|
// Unified cleanup function
|
||||||
|
const cleanup = async (reason: string) => {
|
||||||
|
if (client.extraNonceAndSessionId != null) {
|
||||||
|
await client.destroy();
|
||||||
|
if (reason == 'Error') {
|
||||||
|
this.errorClosure++;
|
||||||
|
} else {
|
||||||
|
this.normalClosure++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!socket.destroyed) {
|
||||||
if (!socket.destroyed) {
|
socket.end();
|
||||||
socket.end();
|
socket.destroy();
|
||||||
socket.destroy();
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// Handle client disconnection
|
||||||
|
socket.on('close', async (hadError: boolean) => {
|
||||||
|
await cleanup(hadError ? "Error" : "Normal Closure");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle socket timeouts
|
||||||
|
socket.on('timeout', async () => {
|
||||||
|
if (socket.bytesRead == 0 || socket.bytesWritten == 0) {
|
||||||
|
this.emptySocket++;
|
||||||
|
} else {
|
||||||
|
this.socketTimeout++;
|
||||||
|
}
|
||||||
|
await cleanup("Timeout");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle errors properly
|
||||||
|
socket.on('error', async (error: Error) => {
|
||||||
|
await cleanup("Error");
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ensure server itself handles errors
|
||||||
|
server.on('error', (err) => {
|
||||||
|
console.error(`Server error: ${err.message}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(port, () => {
|
||||||
|
console.log(`Stratum server is listening on port ${port}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private startSecureSocketServer(port: number) {
|
||||||
|
|
||||||
|
const currentDirectory = process.cwd();
|
||||||
|
const keyPath = path.join(currentDirectory, 'secrets', 'key.pem');
|
||||||
|
const certPath = path.join(currentDirectory, 'secrets', 'cert.pem');
|
||||||
|
|
||||||
|
const tlsOptions: TlsOptions = {
|
||||||
|
key: readFileSync(keyPath),
|
||||||
|
cert: readFileSync(certPath),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle client disconnection
|
const server = createServer(tlsOptions, async (socket: TLSSocket) => {
|
||||||
socket.on('close', async (hadError: boolean) => {
|
// Set 15-minute timeout
|
||||||
await cleanup(hadError ? "Error" : "Normal Closure");
|
socket.setTimeout(1000 * 60 * 15);
|
||||||
|
|
||||||
|
const client = new StratumV1Client(
|
||||||
|
socket,
|
||||||
|
this.stratumV1JobsService,
|
||||||
|
this.bitcoinRpcService,
|
||||||
|
this.clientService,
|
||||||
|
this.clientStatisticsService,
|
||||||
|
this.notificationService,
|
||||||
|
this.blocksService,
|
||||||
|
this.configService,
|
||||||
|
this.addressSettingsService
|
||||||
|
);
|
||||||
|
|
||||||
|
const cleanup = async (reason: string) => {
|
||||||
|
if (client.extraNonceAndSessionId != null) {
|
||||||
|
await client.destroy();
|
||||||
|
if (reason === 'Error') {
|
||||||
|
this.errorClosure++;
|
||||||
|
} else {
|
||||||
|
this.normalClosure++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!socket.destroyed) {
|
||||||
|
socket.end();
|
||||||
|
socket.destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on('close', async (hadError: boolean) => {
|
||||||
|
await cleanup(hadError ? 'Error' : 'Normal Closure');
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('timeout', async () => {
|
||||||
|
if (socket.bytesRead === 0 || socket.bytesWritten === 0) {
|
||||||
|
this.emptySocket++;
|
||||||
|
} else {
|
||||||
|
this.socketTimeout++;
|
||||||
|
}
|
||||||
|
await cleanup('Timeout');
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('error', async (error: Error) => {
|
||||||
|
await cleanup('Error');
|
||||||
|
});
|
||||||
|
|
||||||
|
// your protocol handling stays the same
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle socket timeouts
|
server.on('error', (err) => {
|
||||||
socket.on('timeout', async () => {
|
console.error(`Server error: ${err.message}`);
|
||||||
if(socket.bytesRead == 0 || socket.bytesWritten == 0){
|
|
||||||
this.emptySocket++;
|
|
||||||
}else{
|
|
||||||
this.socketTimeout++;
|
|
||||||
}
|
|
||||||
await cleanup("Timeout");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle errors properly
|
server.listen(port, () => {
|
||||||
socket.on('error', async (error: Error) => {
|
console.log(`Stratum TLS server is listening on port ${port}`);
|
||||||
await cleanup("Error");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ensure server itself handles errors
|
|
||||||
server.on('error', (err) => {
|
|
||||||
console.error(`Server error: ${err.message}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(port, () => {
|
|
||||||
console.log(`Stratum server is listening on port ${port}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user