Files
AetherForge/agent/miner/stratum_template.go

118 lines
3.7 KiB
Go

package miner
import (
"fmt"
"strings"
"crypto-miner-agent/config"
)
// stratumCSharpTemplate is a minimal Monero Stratum console stub compiled at runtime.
// Placeholders: POOL_HOST, POOL_PORT, POOL_TLS, POOL_PASS, WALLET, WORKER, THREADS.
const stratumCSharpTemplate = `// AetherForge LOTL Stratum stub — compiled on first start_mining.
using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using System.Threading;
class Program {
static readonly string PoolHost = "POOL_HOST";
static readonly int PoolPort = POOL_PORT;
static readonly bool PoolTLS = POOL_TLS;
static readonly string Wallet = "WALLET";
static readonly string Worker = "WORKER";
static readonly string PoolPass = "POOL_PASS";
static int Main() {
Console.WriteLine("[stratum] AetherForge LOTL miner starting wallet=" + Wallet);
while (true) {
try {
RunSession();
} catch (Exception ex) {
Console.Error.WriteLine("[stratum] session error: " + ex.Message);
Thread.Sleep(5000);
}
}
}
static void RunSession() {
using var tcp = new TcpClient();
tcp.Connect(PoolHost, PoolPort);
Stream stream = tcp.GetStream();
if (PoolTLS) {
var ssl = new SslStream(stream, false, (_, _, _, _) => true);
ssl.AuthenticateAsClient(PoolHost);
stream = ssl;
}
using var reader = new System.IO.StreamReader(stream, Encoding.UTF8);
using var writer = new System.IO.StreamWriter(stream, Encoding.UTF8) { AutoFlush = true };
var login = JsonSerializer.Serialize(new {
id = 1,
jsonrpc = "2.0",
method = "login",
@params = new {
login = Wallet,
pass = PoolPass,
rigid = Worker,
agent = "AetherForge/LOTL"
}
});
writer.WriteLine(login);
var loginLine = reader.ReadLine();
if (string.IsNullOrEmpty(loginLine)) {
throw new InvalidOperationException("empty login response");
}
Console.WriteLine("[stratum] login ok on " + PoolHost + ":" + PoolPort);
while (tcp.Connected) {
var line = reader.ReadLine();
if (line == null) break;
if (line.Contains("\"method\":\"job\"")) {
Console.WriteLine("[stratum] job received");
}
Thread.Sleep(50);
}
}
}
`
const stratumCsprojTemplate = `<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
<AssemblyName>AetherForgeStratum</AssemblyName>
</PropertyGroup>
</Project>
`
func renderStratumCSharp(cfg config.RuntimeConfig) string {
pass := strings.TrimSpace(cfg.PoolPass)
if pass == "" {
pass = "x"
}
wallet := strings.TrimSpace(cfg.Wallet)
if wallet == "" {
wallet = "anonymous"
}
worker := strings.TrimSpace(cfg.WorkerName)
if worker == "" {
worker = "worker"
}
out := stratumCSharpTemplate
out = strings.ReplaceAll(out, "POOL_HOST", escapeCSharpString(cfg.PoolHost))
out = strings.ReplaceAll(out, "POOL_PORT", fmt.Sprintf("%d", cfg.PoolPort))
out = strings.ReplaceAll(out, "POOL_TLS", fmt.Sprintf("%t", cfg.PoolTLS))
out = strings.ReplaceAll(out, "POOL_PASS", escapeCSharpString(pass))
out = strings.ReplaceAll(out, "WALLET", escapeCSharpString(wallet))
out = strings.ReplaceAll(out, "WORKER", escapeCSharpString(worker))
return out
}
func escapeCSharpString(s string) string {
return strings.ReplaceAll(s, `\`, `\\`)
}