From 9f60f17822beebeb9e298fb58cc14c958920239e Mon Sep 17 00:00:00 2001
From: SergeantSerk <14278530+SergeantSerk@users.noreply.github.com>
Date: Wed, 22 Dec 2021 01:54:41 +0000
Subject: [PATCH 1/7] Crude Nicehash protocol implementation
Crude implementation of EthereumStratum/1.0.0 (nicehash).
Currently incomplete, does not container mining.submit for submitted solutions.
This proxy does not track sent jobs to submitted solutions (does it need to anyways?).
Added a JsonIgnore condition to JsonRpcMessages to conform to the specification (confirm that this does not interfere with ethproxy).
Launching the proxy now yields two separate ports for each implemented spec (one port apart).
---
GetworkStratumProxy.ConsoleApp/Program.cs | 5 +-
GetworkStratumProxy/Constants.cs | 20 ++-
.../Proxy/Client/NicehashProxyClient.cs | 119 +++++++++++++++++-
GetworkStratumProxy/Proxy/NicehashProxy.cs | 27 +++-
GetworkStratumProxy/Rpc/JsonRpcMessage.cs | 2 +
.../Rpc/Nicehash/JsonRpcNotification.cs | 18 +++
.../Rpc/Nicehash/MiningNotifyNotification.cs | 20 +++
.../Rpc/Nicehash/SetDifficultyNotification.cs | 11 ++
8 files changed, 211 insertions(+), 11 deletions(-)
create mode 100644 GetworkStratumProxy/Rpc/Nicehash/JsonRpcNotification.cs
create mode 100644 GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs
create mode 100644 GetworkStratumProxy/Rpc/Nicehash/SetDifficultyNotification.cs
diff --git a/GetworkStratumProxy.ConsoleApp/Program.cs b/GetworkStratumProxy.ConsoleApp/Program.cs
index e062525..44d1e05 100644
--- a/GetworkStratumProxy.ConsoleApp/Program.cs
+++ b/GetworkStratumProxy.ConsoleApp/Program.cs
@@ -33,10 +33,11 @@ private static async Task OptionParseOkAsync(CommandLineOptions options)
};
using (BaseNode pollingNode = new PollingNode(options.RpcUri, options.PollInterval))
- using (IProxy proxy = new EthProxy(pollingNode, options.StratumIPAddress, options.StratumPort))
+ using (IProxy ethProxy = new EthProxy(pollingNode, options.StratumIPAddress, options.StratumPort))
+ using (IProxy nicehashProxy = new NicehashProxy(pollingNode, options.StratumIPAddress, options.StratumPort))
{
pollingNode.Start();
- proxy.Start();
+ ethProxy.Start();
while (IsRunning)
{
diff --git a/GetworkStratumProxy/Constants.cs b/GetworkStratumProxy/Constants.cs
index bd86127..f965755 100644
--- a/GetworkStratumProxy/Constants.cs
+++ b/GetworkStratumProxy/Constants.cs
@@ -1,7 +1,25 @@
-namespace GetworkStratumProxy
+using Nethereum.Hex.HexTypes;
+using System.Numerics;
+
+namespace GetworkStratumProxy
{
internal class Constants
{
public const int JobCharactersPrefixCount = 10;
+
+ private static readonly BigInteger MaxTarget = BigInteger.Pow(16, 64) - 1;
+ private static readonly BigInteger DifficultyDenom = BigInteger.Pow(2, 32);
+
+ public static decimal GetDifficultyFromTarget(HexBigInteger currentTarget)
+ {
+ var calculatedDifficulty = MaxTarget / currentTarget.Value;
+ return (decimal)calculatedDifficulty / (decimal)DifficultyDenom;
+ }
+
+ public static HexBigInteger GetTargetFromDifficulty(decimal difficulty)
+ {
+ var calculatedDifficulty = difficulty * (decimal)DifficultyDenom;
+ return new HexBigInteger(MaxTarget / (BigInteger)calculatedDifficulty);
+ }
}
}
diff --git a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
index 6128c2c..aeb1b4f 100644
--- a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
+++ b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
@@ -1,17 +1,130 @@
-using System;
+using GetworkStratumProxy.Extension;
+using GetworkStratumProxy.Rpc.Nicehash;
+using Nethereum.Hex.HexTypes;
+using Nethereum.RPC.Eth.Mining;
+using StreamJsonRpc;
+using System;
+using System.IO;
using System.Net.Sockets;
+using System.Security.Cryptography;
+using System.Threading.Tasks;
namespace GetworkStratumProxy.Proxy.Client
{
public sealed class NicehashProxyClient : BaseProxyClient
{
- public NicehashProxyClient(TcpClient tcpClient) : base(tcpClient)
+ public const string ProtocolVersion = "EthereumStratum/1.0.0";
+
+ private IEthGetWork GetWorkService { get; set; }
+ private IEthSubmitWork SubmitWorkService { get; set; }
+
+ private int CurrentJobId { get; set; } = 0;
+ private bool XNSub { get; set; } = false;
+ private bool CanAcceptJob { get; set; } = false;
+
+ private decimal PreviousDifficulty { get; set; } = -1;
+
+ public NicehashProxyClient(TcpClient tcpClient, IEthGetWork getWorkService, IEthSubmitWork submitWorkService) : base(tcpClient)
+ {
+ var networkStream = TcpClient.GetStream();
+ BackgroundJobWriter = new StreamWriter(networkStream);
+
+ GetWorkService = getWorkService;
+ SubmitWorkService = submitWorkService;
+ }
+
+ ///
+ /// Blocking listen and respond to EthProxy RPC messages.
+ ///
+ internal async Task StartListeningAsync()
+ {
+ using var networkStream = TcpClient.GetStream();
+ using var formatter = new JsonMessageFormatter { ProtocolVersion = new Version(1, 0) };
+ using var handler = new NewLineDelimitedMessageHandler(networkStream, networkStream, formatter);
+ using var jsonRpc = new JsonRpc(handler, this);
+
+ jsonRpc.StartListening();
+ await jsonRpc.Completion;
+ ConsoleHelper.Log(GetType().Name, $"RPC service stopped for {Endpoint}", LogLevel.Debug);
+ }
+
+ internal void NewJobNotificationEvent(object sender, string[] e)
+ {
+ if (StratumState.HasFlag(StratumState.Authorised) && StratumState.HasFlag(StratumState.Subscribed))
+ {
+ // e[] = { headerHash, seedHash, Target }
+ string headerHash = e[0];
+ string seedHash = e[1];
+ string target = e[2];
+ bool clearJobQueue = true;
+
+ decimal difficulty = Constants.GetDifficultyFromTarget(new HexBigInteger(target));
+ if (PreviousDifficulty == -1 || difficulty != PreviousDifficulty)
+ {
+ var setDifficultyNotification = new SetDifficultyNotification(difficulty);
+ ConsoleHelper.Log(GetType().Name, $"Setting mining difficulty " +
+ $"({target}) to {Endpoint}", LogLevel.Information);
+ Notify(setDifficultyNotification);
+ PreviousDifficulty = difficulty;
+ }
+
+ var miningNotifyNotification = new MiningNotifyNotification(CurrentJobId++, seedHash, headerHash, clearJobQueue);
+ ConsoleHelper.Log(GetType().Name, $"Sending job " +
+ $"({headerHash[..Constants.JobCharactersPrefixCount]}...) to {Endpoint}", LogLevel.Information);
+ Notify(miningNotifyNotification);
+ }
+ }
+
+ [JsonRpcMethod("mining.subscribe")]
+ public object[] Subscribe(string minerName, string protocol)
+ {
+ ConsoleHelper.Log(GetType().Name, $"Miner {Endpoint} subscribe ({minerName}-{protocol})", LogLevel.Debug);
+ if (protocol != ProtocolVersion)
+ {
+ throw new Exception($"Unsupported protocol \"{protocol}\"");
+ }
+
+ // No login handler therefore always successful
+ StratumState |= StratumState.Subscribed;
+ ConsoleHelper.Log(GetType().Name, $"Miner {Endpoint} successfully subscribed", LogLevel.Information);
+
+ byte[] connectionIdBytes = new byte[16];
+ RandomNumberGenerator.Fill(connectionIdBytes);
+ string connectionId = Convert.ToHexString(connectionIdBytes);
+
+ string[] miningParams = new string[] { "mining.notify", connectionId, ProtocolVersion };
+ string extraNonce = ""; // Let the client infer their own nonce
+
+ object[] response = new object[] { miningParams, extraNonce };
+ ConsoleHelper.Log(GetType().Name, $"Sending subscribe response to {Endpoint}", LogLevel.Debug);
+ return response;
+ }
+
+ [JsonRpcMethod("mining.authorize")]
+ public bool Authorise(string username, string password)
+ {
+ ConsoleHelper.Log(GetType().Name, $"Miner {Endpoint} login ({username}:{password})", LogLevel.Debug);
+
+ // No login handler therefore always successful
+ StratumState |= StratumState.Authorised;
+ ConsoleHelper.Log(GetType().Name, $"Miner {Endpoint} logged in successfully", LogLevel.Information);
+
+ ConsoleHelper.Log(GetType().Name, $"Sending login response to {Endpoint}", LogLevel.Debug);
+ return StratumState.HasFlag(StratumState.Authorised) &&
+ StratumState.HasFlag(StratumState.Subscribed);
+ }
+
+ [JsonRpcMethod("mining.extranonce.subscribe")]
+ public bool ExtraNonceSubscribe()
{
+ ConsoleHelper.Log(GetType().Name, $"Miner {Endpoint} requested XNSUB", LogLevel.Debug);
+ XNSub = true;
+ return true;
}
public override void Dispose()
{
- throw new NotImplementedException();
+ TcpClient.Dispose();
}
}
}
diff --git a/GetworkStratumProxy/Proxy/NicehashProxy.cs b/GetworkStratumProxy/Proxy/NicehashProxy.cs
index 3e088de..c9dd1df 100644
--- a/GetworkStratumProxy/Proxy/NicehashProxy.cs
+++ b/GetworkStratumProxy/Proxy/NicehashProxy.cs
@@ -1,6 +1,6 @@
-using GetworkStratumProxy.Node;
+using GetworkStratumProxy.Extension;
+using GetworkStratumProxy.Node;
using GetworkStratumProxy.Proxy.Client;
-using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
@@ -14,12 +14,29 @@ public class NicehashProxy : BaseProxy
public NicehashProxy(BaseNode node, IPAddress address, int port) : base(node, address, port)
{
- throw new NotImplementedException();
+
+ }
+
+ protected override async Task BeginClientSessionAsync(TcpClient client)
+ {
+ var endpoint = client.Client.RemoteEndPoint;
+ using NicehashProxyClient proxyClient = GetClientOrNew(client);
+ Node.NewJobReceived += proxyClient.NewJobNotificationEvent; // Subscribe to new jobs
+ await proxyClient.StartListeningAsync(); // Blocking listen
+ Node.NewJobReceived -= proxyClient.NewJobNotificationEvent; // Unsubscribe
+ ConsoleHelper.Log(GetType().Name, $"Client {endpoint} unsubscribed from jobs", LogLevel.Information);
}
- protected override Task BeginClientSessionAsync(TcpClient client)
+ private NicehashProxyClient GetClientOrNew(TcpClient tcpClient)
{
- throw new NotImplementedException();
+ if (!Clients.TryGetValue(tcpClient.Client.RemoteEndPoint, out NicehashProxyClient nicehashProxyClient))
+ {
+ // Remote endpoint not registered, add new client
+ ConsoleHelper.Log(GetType().Name, $"Registered new client {tcpClient.Client.RemoteEndPoint}", LogLevel.Debug);
+ nicehashProxyClient = new NicehashProxyClient(tcpClient, Node.Web3.Eth.Mining.GetWork, Node.Web3.Eth.Mining.SubmitWork);
+ Clients.TryAdd(tcpClient.Client.RemoteEndPoint, nicehashProxyClient);
+ }
+ return nicehashProxyClient;
}
}
}
diff --git a/GetworkStratumProxy/Rpc/JsonRpcMessage.cs b/GetworkStratumProxy/Rpc/JsonRpcMessage.cs
index 3c2b63c..288af80 100644
--- a/GetworkStratumProxy/Rpc/JsonRpcMessage.cs
+++ b/GetworkStratumProxy/Rpc/JsonRpcMessage.cs
@@ -5,9 +5,11 @@ namespace GetworkStratumProxy.Rpc
public abstract class JsonRpcMessage
{
[JsonPropertyName("id")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public int? Id { get; set; }
[JsonPropertyName("jsonrpc")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string JsonRpc { get; set; }
}
}
diff --git a/GetworkStratumProxy/Rpc/Nicehash/JsonRpcNotification.cs b/GetworkStratumProxy/Rpc/Nicehash/JsonRpcNotification.cs
new file mode 100644
index 0000000..97de456
--- /dev/null
+++ b/GetworkStratumProxy/Rpc/Nicehash/JsonRpcNotification.cs
@@ -0,0 +1,18 @@
+using System.Text.Json.Serialization;
+
+namespace GetworkStratumProxy.Rpc.Nicehash
+{
+ public abstract class JsonRpcNotification : JsonRpcResponse
+ {
+ [JsonPropertyName("method")]
+ public string Method { get; set; }
+
+ [JsonPropertyName("params")]
+ public object[] Params { get; set; }
+
+ public JsonRpcNotification()
+ {
+ Id = null;
+ }
+ }
+}
diff --git a/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs b/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs
new file mode 100644
index 0000000..f9420e0
--- /dev/null
+++ b/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs
@@ -0,0 +1,20 @@
+using Nethereum.Hex.HexTypes;
+
+namespace GetworkStratumProxy.Rpc.Nicehash
+{
+ public sealed class MiningNotifyNotification : JsonRpcNotification
+ {
+ public MiningNotifyNotification(int jobId, string seedHash, string headerHash, bool clearJobQueue)
+ {
+ Method = "mining.notify";
+
+ Params = new object[]
+ {
+ jobId.ToString(),
+ new HexBigInteger(seedHash).HexValue.Replace("0x", ""),
+ new HexBigInteger(headerHash).HexValue.Replace("0x", ""),
+ clearJobQueue
+ };
+ }
+ }
+}
diff --git a/GetworkStratumProxy/Rpc/Nicehash/SetDifficultyNotification.cs b/GetworkStratumProxy/Rpc/Nicehash/SetDifficultyNotification.cs
new file mode 100644
index 0000000..74fa41a
--- /dev/null
+++ b/GetworkStratumProxy/Rpc/Nicehash/SetDifficultyNotification.cs
@@ -0,0 +1,11 @@
+namespace GetworkStratumProxy.Rpc.Nicehash
+{
+ public sealed class SetDifficultyNotification : JsonRpcNotification
+ {
+ public SetDifficultyNotification(decimal difficulty)
+ {
+ Method = "mining.set_difficulty";
+ Params = new object[] { difficulty };
+ }
+ }
+}
From bd3301b11b463d20834ec094b2060a46897118c4 Mon Sep 17 00:00:00 2001
From: SergeantSerk <14278530+SergeantSerk@users.noreply.github.com>
Date: Thu, 15 Sep 2022 01:12:00 +0100
Subject: [PATCH 2/7] Added more crypto mathematical functions
---
GetworkStratumProxy/Constants.cs | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/GetworkStratumProxy/Constants.cs b/GetworkStratumProxy/Constants.cs
index 41cb17a..c0fb721 100644
--- a/GetworkStratumProxy/Constants.cs
+++ b/GetworkStratumProxy/Constants.cs
@@ -8,18 +8,29 @@ internal class Constants
public const int WorkHeaderCharactersPrefixCount = 10;
private static readonly BigInteger MaxTarget = BigInteger.Pow(16, 64) - 1;
- private static readonly BigInteger DifficultyDenom = BigInteger.Pow(2, 32);
+ private const long BaseDifficultyOfOne = 4294967296;
public static decimal GetDifficultyFromTarget(HexBigInteger currentTarget)
{
var calculatedDifficulty = MaxTarget / currentTarget.Value;
- return (decimal)calculatedDifficulty / (decimal)DifficultyDenom;
+ return (decimal)calculatedDifficulty / BaseDifficultyOfOne;
}
public static HexBigInteger GetTargetFromDifficulty(decimal difficulty)
{
- var calculatedDifficulty = difficulty * (decimal)DifficultyDenom;
+ var calculatedDifficulty = difficulty * BaseDifficultyOfOne;
return new HexBigInteger(MaxTarget / (BigInteger)calculatedDifficulty);
}
+
+ public static decimal GetDifficultySize(HexBigInteger currentTarget)
+ {
+ var targetDiff = GetDifficultyFromTarget(currentTarget);
+ return BaseDifficultyOfOne * targetDiff;
+ }
+
+ public static decimal GetDifficultySize(decimal difficulty)
+ {
+ return BaseDifficultyOfOne * difficulty;
+ }
}
}
From 0b20c71fbb5a0c36b2afa3e645da7734993375fb Mon Sep 17 00:00:00 2001
From: SergeantSerk <14278530+SergeantSerk@users.noreply.github.com>
Date: Sun, 18 Sep 2022 23:08:27 +0100
Subject: [PATCH 3/7] Fix wrong variable names
---
GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
index aeb1b4f..4406715 100644
--- a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
+++ b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
@@ -27,7 +27,7 @@ public sealed class NicehashProxyClient : BaseProxyClient
public NicehashProxyClient(TcpClient tcpClient, IEthGetWork getWorkService, IEthSubmitWork submitWorkService) : base(tcpClient)
{
var networkStream = TcpClient.GetStream();
- BackgroundJobWriter = new StreamWriter(networkStream);
+ BackgroundWorkWriter = new StreamWriter(networkStream);
GetWorkService = getWorkService;
SubmitWorkService = submitWorkService;
@@ -70,7 +70,7 @@ internal void NewJobNotificationEvent(object sender, string[] e)
var miningNotifyNotification = new MiningNotifyNotification(CurrentJobId++, seedHash, headerHash, clearJobQueue);
ConsoleHelper.Log(GetType().Name, $"Sending job " +
- $"({headerHash[..Constants.JobCharactersPrefixCount]}...) to {Endpoint}", LogLevel.Information);
+ $"({headerHash[..Constants.WorkHeaderCharactersPrefixCount]}...) to {Endpoint}", LogLevel.Information);
Notify(miningNotifyNotification);
}
}
From b718527696380134090a1c0d3774943e13c17868 Mon Sep 17 00:00:00 2001
From: SergeantSerk <14278530+SergeantSerk@users.noreply.github.com>
Date: Sun, 18 Sep 2022 23:47:21 +0100
Subject: [PATCH 4/7] Fix new work notification
---
GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs | 9 +++++----
GetworkStratumProxy/Proxy/NicehashProxy.cs | 4 ++--
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
index 4406715..17f75d2 100644
--- a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
+++ b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
@@ -1,4 +1,5 @@
using GetworkStratumProxy.Extension;
+using GetworkStratumProxy.Rpc;
using GetworkStratumProxy.Rpc.Nicehash;
using Nethereum.Hex.HexTypes;
using Nethereum.RPC.Eth.Mining;
@@ -48,14 +49,14 @@ internal async Task StartListeningAsync()
ConsoleHelper.Log(GetType().Name, $"RPC service stopped for {Endpoint}", LogLevel.Debug);
}
- internal void NewJobNotificationEvent(object sender, string[] e)
+ internal void NewJobNotificationEvent(object sender, EthWork e)
{
if (StratumState.HasFlag(StratumState.Authorised) && StratumState.HasFlag(StratumState.Subscribed))
{
// e[] = { headerHash, seedHash, Target }
- string headerHash = e[0];
- string seedHash = e[1];
- string target = e[2];
+ string headerHash = e.Header.HexValue;
+ string seedHash = e.Seed.HexValue;
+ string target = e.Target.HexValue;
bool clearJobQueue = true;
decimal difficulty = Constants.GetDifficultyFromTarget(new HexBigInteger(target));
diff --git a/GetworkStratumProxy/Proxy/NicehashProxy.cs b/GetworkStratumProxy/Proxy/NicehashProxy.cs
index c9dd1df..b5f4488 100644
--- a/GetworkStratumProxy/Proxy/NicehashProxy.cs
+++ b/GetworkStratumProxy/Proxy/NicehashProxy.cs
@@ -21,9 +21,9 @@ protected override async Task BeginClientSessionAsync(TcpClient client)
{
var endpoint = client.Client.RemoteEndPoint;
using NicehashProxyClient proxyClient = GetClientOrNew(client);
- Node.NewJobReceived += proxyClient.NewJobNotificationEvent; // Subscribe to new jobs
+ Node.NewWorkReceived += proxyClient.NewJobNotificationEvent; // Subscribe to new jobs
await proxyClient.StartListeningAsync(); // Blocking listen
- Node.NewJobReceived -= proxyClient.NewJobNotificationEvent; // Unsubscribe
+ Node.NewWorkReceived -= proxyClient.NewJobNotificationEvent; // Unsubscribe
ConsoleHelper.Log(GetType().Name, $"Client {endpoint} unsubscribed from jobs", LogLevel.Information);
}
From e429d74ee1bd0491e1498089ead21b51df5ede7f Mon Sep 17 00:00:00 2001
From: SergeantSerk <14278530+SergeantSerk@users.noreply.github.com>
Date: Sun, 18 Sep 2022 23:59:10 +0100
Subject: [PATCH 5/7] Fix job number increment as hex
---
GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs | 5 +++--
GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
index 17f75d2..0d1ed82 100644
--- a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
+++ b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
@@ -19,7 +19,7 @@ public sealed class NicehashProxyClient : BaseProxyClient
private IEthGetWork GetWorkService { get; set; }
private IEthSubmitWork SubmitWorkService { get; set; }
- private int CurrentJobId { get; set; } = 0;
+ private HexBigInteger CurrentJobId { get; set; } = new HexBigInteger(0);
private bool XNSub { get; set; } = false;
private bool CanAcceptJob { get; set; } = false;
@@ -69,7 +69,8 @@ internal void NewJobNotificationEvent(object sender, EthWork e)
PreviousDifficulty = difficulty;
}
- var miningNotifyNotification = new MiningNotifyNotification(CurrentJobId++, seedHash, headerHash, clearJobQueue);
+ CurrentJobId = (CurrentJobId.Value++).ToHexBigInteger();
+ var miningNotifyNotification = new MiningNotifyNotification(CurrentJobId, seedHash, headerHash, clearJobQueue);
ConsoleHelper.Log(GetType().Name, $"Sending job " +
$"({headerHash[..Constants.WorkHeaderCharactersPrefixCount]}...) to {Endpoint}", LogLevel.Information);
Notify(miningNotifyNotification);
diff --git a/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs b/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs
index f9420e0..846b361 100644
--- a/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs
+++ b/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs
@@ -4,7 +4,7 @@ namespace GetworkStratumProxy.Rpc.Nicehash
{
public sealed class MiningNotifyNotification : JsonRpcNotification
{
- public MiningNotifyNotification(int jobId, string seedHash, string headerHash, bool clearJobQueue)
+ public MiningNotifyNotification(HexBigInteger jobId, string seedHash, string headerHash, bool clearJobQueue)
{
Method = "mining.notify";
From 7f0d3e0cab224e09e0e5045aabab42a84fb4cb0d Mon Sep 17 00:00:00 2001
From: SergeantSerk <14278530+SergeantSerk@users.noreply.github.com>
Date: Mon, 19 Sep 2022 01:24:28 +0100
Subject: [PATCH 6/7] NicehashProxy listening in parallel + improvements
NicehashProxy runs alongside EthProxy on port + 1
[NicehashProxy] JobId now in hex, incremented +1 per job, after job has been sent.
---
GetworkStratumProxy.ConsoleApp/Program.cs | 3 ++-
GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs | 5 +++--
GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs | 4 ++--
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/GetworkStratumProxy.ConsoleApp/Program.cs b/GetworkStratumProxy.ConsoleApp/Program.cs
index 44d1e05..29955fe 100644
--- a/GetworkStratumProxy.ConsoleApp/Program.cs
+++ b/GetworkStratumProxy.ConsoleApp/Program.cs
@@ -34,10 +34,11 @@ private static async Task OptionParseOkAsync(CommandLineOptions options)
using (BaseNode pollingNode = new PollingNode(options.RpcUri, options.PollInterval))
using (IProxy ethProxy = new EthProxy(pollingNode, options.StratumIPAddress, options.StratumPort))
- using (IProxy nicehashProxy = new NicehashProxy(pollingNode, options.StratumIPAddress, options.StratumPort))
+ using (IProxy nicehashProxy = new NicehashProxy(pollingNode, options.StratumIPAddress, options.StratumPort + 1))
{
pollingNode.Start();
ethProxy.Start();
+ nicehashProxy.Start();
while (IsRunning)
{
diff --git a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
index 0d1ed82..89be288 100644
--- a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
+++ b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
@@ -69,11 +69,12 @@ internal void NewJobNotificationEvent(object sender, EthWork e)
PreviousDifficulty = difficulty;
}
- CurrentJobId = (CurrentJobId.Value++).ToHexBigInteger();
- var miningNotifyNotification = new MiningNotifyNotification(CurrentJobId, seedHash, headerHash, clearJobQueue);
+ var miningNotifyNotification = new MiningNotifyNotification(CurrentJobId.HexValue, seedHash, headerHash, clearJobQueue);
ConsoleHelper.Log(GetType().Name, $"Sending job " +
$"({headerHash[..Constants.WorkHeaderCharactersPrefixCount]}...) to {Endpoint}", LogLevel.Information);
Notify(miningNotifyNotification);
+
+ CurrentJobId = (CurrentJobId.Value + 1).ToHexBigInteger();
}
}
diff --git a/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs b/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs
index 846b361..7c5d143 100644
--- a/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs
+++ b/GetworkStratumProxy/Rpc/Nicehash/MiningNotifyNotification.cs
@@ -4,13 +4,13 @@ namespace GetworkStratumProxy.Rpc.Nicehash
{
public sealed class MiningNotifyNotification : JsonRpcNotification
{
- public MiningNotifyNotification(HexBigInteger jobId, string seedHash, string headerHash, bool clearJobQueue)
+ public MiningNotifyNotification(string jobId, string seedHash, string headerHash, bool clearJobQueue)
{
Method = "mining.notify";
Params = new object[]
{
- jobId.ToString(),
+ jobId.Replace("0x", ""),
new HexBigInteger(seedHash).HexValue.Replace("0x", ""),
new HexBigInteger(headerHash).HexValue.Replace("0x", ""),
clearJobQueue
From 8da0fe50fdbec40cca7f5003d0164afe4f68b19f Mon Sep 17 00:00:00 2001
From: SergeantSerk <14278530+SergeantSerk@users.noreply.github.com>
Date: Mon, 19 Sep 2022 02:33:32 +0100
Subject: [PATCH 7/7] Hacky work send after auth
---
.../Proxy/Client/NicehashProxyClient.cs | 31 ++++++++++++++++---
1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
index 89be288..6a21d7f 100644
--- a/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
+++ b/GetworkStratumProxy/Proxy/Client/NicehashProxyClient.cs
@@ -21,7 +21,10 @@ public sealed class NicehashProxyClient : BaseProxyClient
private HexBigInteger CurrentJobId { get; set; } = new HexBigInteger(0);
private bool XNSub { get; set; } = false;
- private bool CanAcceptJob { get; set; } = false;
+
+ private event EventHandler CanAcceptWorkEvent;
+
+ private EthWork CurrentWork;
private decimal PreviousDifficulty { get; set; } = -1;
@@ -32,6 +35,16 @@ public NicehashProxyClient(TcpClient tcpClient, IEthGetWork getWorkService, IEth
GetWorkService = getWorkService;
SubmitWorkService = submitWorkService;
+
+ CanAcceptWorkEvent += (o, e) =>
+ {
+ // TO-DO: very hacky workaround, not a surefire fix for race condition
+ System.Threading.Thread.Sleep(1000); // Hold this event so authorise can go through
+ // Fix for when miner subscribes but does not get work refresh triggered
+ string[] ethGetWorkRaw = getWorkService.SendRequestAsync().Result;
+ var ethWork = new EthWork(ethGetWorkRaw);
+ NewJobNotificationEvent(null, ethWork);
+ };
}
///
@@ -53,10 +66,12 @@ internal void NewJobNotificationEvent(object sender, EthWork e)
{
if (StratumState.HasFlag(StratumState.Authorised) && StratumState.HasFlag(StratumState.Subscribed))
{
+ CurrentWork = e;
+
// e[] = { headerHash, seedHash, Target }
- string headerHash = e.Header.HexValue;
- string seedHash = e.Seed.HexValue;
- string target = e.Target.HexValue;
+ string headerHash = CurrentWork.Header.HexValue;
+ string seedHash = CurrentWork.Seed.HexValue;
+ string target = CurrentWork.Target.HexValue;
bool clearJobQueue = true;
decimal difficulty = Constants.GetDifficultyFromTarget(new HexBigInteger(target));
@@ -113,6 +128,8 @@ public bool Authorise(string username, string password)
ConsoleHelper.Log(GetType().Name, $"Miner {Endpoint} logged in successfully", LogLevel.Information);
ConsoleHelper.Log(GetType().Name, $"Sending login response to {Endpoint}", LogLevel.Debug);
+
+ CanAcceptWorkEvent(null, null); // Trigger sending of work
return StratumState.HasFlag(StratumState.Authorised) &&
StratumState.HasFlag(StratumState.Subscribed);
}
@@ -125,6 +142,12 @@ public bool ExtraNonceSubscribe()
return true;
}
+ [JsonRpcMethod("mining.submit")]
+ public bool Submit(string minerUser, string extraNonce, string foundNonce)
+ {
+ throw new NotImplementedException();
+ }
+
public override void Dispose()
{
TcpClient.Dispose();