commit 6b42407d97eaea379caafd081909cb394e0c3cdd Author: Harald Wolff Date: Tue Oct 17 22:07:00 2017 +0200 Reorganization Progress (submodules) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e82d27 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# Autosave files +*~ + +# build +[Oo]bj/ +[Bb]in/ +packages/ +TestResults/ + +# globs +Makefile.in +*.DS_Store +*.sln.cache +*.suo +*.cache +*.pidb +*.userprefs +*.usertasks +config.log +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.user +*.tar.gz +tarballs/ +test-results/ +Thumbs.db + +# Mac bundle stuff +*.dmg +*.app + +# resharper +*_Resharper.* +*.Resharper + +# dotCover +*.dotCover diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..0830d8e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "sharp-crypto"] + path = sharp-crypto + url = git@schwann.lnvpn.de:LupusNobilis/sharp-crypto.git +[submodule "sharp-biginteger"] + path = sharp-biginteger + url = git@schwann.lnvpn.de:haraldwolff/sharp-biginteger.git diff --git a/SharpMining.sln b/SharpMining.sln new file mode 100644 index 0000000..f733ab8 --- /dev/null +++ b/SharpMining.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpMining", "SharpMining\SharpMining.csproj", "{5AE4E72A-253B-4FBD-AD5E-C038D57571D0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleLogger", "SimpleLogger\SimpleLogger.csproj", "{991FEB35-A35C-460D-A215-B8A29842E37B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sharp.cryptonote", "sharp-cryptonote-tool\sharp.cryptonote.csproj", "{52C68C13-2DC2-438A-9EC1-E8C4953B07DF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sharp.jsonrpc", "sharp-jsonrpc\sharp.jsonrpc.csproj", "{DCE6066E-9709-4D12-8994-F7879C3557D6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sharp.hashing", "sharp-hashing\sharp.hashing.csproj", "{CCD7C196-B079-4AA7-98AF-5BECAD089CE4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sharp.extensions", "sharp-extensions\sharp.extensions.csproj", "{97CA3CA9-98B3-4492-B072-D7A5995B68E9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BigInt", "BigInteger\BigInt.csproj", "{E745E261-9E3E-4401-B3BA-78B38753A82E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BigIntegerTest", "BigIntegerTest\BigIntegerTest.csproj", "{9596C70F-9CCD-4821-A82B-501B97544D52}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crypto", "Crypto\Crypto.csproj", "{15D8398F-01EB-4280-8E2E-B03417DD3215}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5AE4E72A-253B-4FBD-AD5E-C038D57571D0}.Debug|x86.ActiveCfg = Debug|x86 + {5AE4E72A-253B-4FBD-AD5E-C038D57571D0}.Debug|x86.Build.0 = Debug|x86 + {5AE4E72A-253B-4FBD-AD5E-C038D57571D0}.Release|x86.ActiveCfg = Release|x86 + {5AE4E72A-253B-4FBD-AD5E-C038D57571D0}.Release|x86.Build.0 = Release|x86 + {991FEB35-A35C-460D-A215-B8A29842E37B}.Debug|x86.ActiveCfg = Debug|Any CPU + {991FEB35-A35C-460D-A215-B8A29842E37B}.Debug|x86.Build.0 = Debug|Any CPU + {991FEB35-A35C-460D-A215-B8A29842E37B}.Release|x86.ActiveCfg = Release|Any CPU + {991FEB35-A35C-460D-A215-B8A29842E37B}.Release|x86.Build.0 = Release|Any CPU + {52C68C13-2DC2-438A-9EC1-E8C4953B07DF}.Debug|x86.ActiveCfg = Debug|Any CPU + {52C68C13-2DC2-438A-9EC1-E8C4953B07DF}.Debug|x86.Build.0 = Debug|Any CPU + {52C68C13-2DC2-438A-9EC1-E8C4953B07DF}.Release|x86.ActiveCfg = Release|Any CPU + {52C68C13-2DC2-438A-9EC1-E8C4953B07DF}.Release|x86.Build.0 = Release|Any CPU + {DCE6066E-9709-4D12-8994-F7879C3557D6}.Debug|x86.ActiveCfg = Debug|Any CPU + {DCE6066E-9709-4D12-8994-F7879C3557D6}.Debug|x86.Build.0 = Debug|Any CPU + {DCE6066E-9709-4D12-8994-F7879C3557D6}.Release|x86.ActiveCfg = Release|Any CPU + {DCE6066E-9709-4D12-8994-F7879C3557D6}.Release|x86.Build.0 = Release|Any CPU + {CCD7C196-B079-4AA7-98AF-5BECAD089CE4}.Debug|x86.ActiveCfg = Debug|Any CPU + {CCD7C196-B079-4AA7-98AF-5BECAD089CE4}.Debug|x86.Build.0 = Debug|Any CPU + {CCD7C196-B079-4AA7-98AF-5BECAD089CE4}.Release|x86.ActiveCfg = Release|Any CPU + {CCD7C196-B079-4AA7-98AF-5BECAD089CE4}.Release|x86.Build.0 = Release|Any CPU + {97CA3CA9-98B3-4492-B072-D7A5995B68E9}.Debug|x86.ActiveCfg = Debug|Any CPU + {97CA3CA9-98B3-4492-B072-D7A5995B68E9}.Debug|x86.Build.0 = Debug|Any CPU + {97CA3CA9-98B3-4492-B072-D7A5995B68E9}.Release|x86.ActiveCfg = Release|Any CPU + {97CA3CA9-98B3-4492-B072-D7A5995B68E9}.Release|x86.Build.0 = Release|Any CPU + {E745E261-9E3E-4401-B3BA-78B38753A82E}.Debug|x86.ActiveCfg = Debug|Any CPU + {E745E261-9E3E-4401-B3BA-78B38753A82E}.Debug|x86.Build.0 = Debug|Any CPU + {E745E261-9E3E-4401-B3BA-78B38753A82E}.Release|x86.ActiveCfg = Release|Any CPU + {E745E261-9E3E-4401-B3BA-78B38753A82E}.Release|x86.Build.0 = Release|Any CPU + {9596C70F-9CCD-4821-A82B-501B97544D52}.Debug|x86.ActiveCfg = Debug|x86 + {9596C70F-9CCD-4821-A82B-501B97544D52}.Debug|x86.Build.0 = Debug|x86 + {9596C70F-9CCD-4821-A82B-501B97544D52}.Release|x86.ActiveCfg = Release|x86 + {9596C70F-9CCD-4821-A82B-501B97544D52}.Release|x86.Build.0 = Release|x86 + {15D8398F-01EB-4280-8E2E-B03417DD3215}.Debug|x86.ActiveCfg = Debug|Any CPU + {15D8398F-01EB-4280-8E2E-B03417DD3215}.Debug|x86.Build.0 = Debug|Any CPU + {15D8398F-01EB-4280-8E2E-B03417DD3215}.Release|x86.ActiveCfg = Release|Any CPU + {15D8398F-01EB-4280-8E2E-B03417DD3215}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + Policies = $0 + $0.DotNetNamingPolicy = $1 + $1.DirectoryNamespaceAssociation = PrefixedHierarchical + $1.ResourceNamePolicy = FileFormatDefault + $0.VersionControlPolicy = $2 + $2.inheritsSet = Mono + EndGlobalSection +EndGlobal diff --git a/SharpMining/.gitignore b/SharpMining/.gitignore new file mode 100644 index 0000000..4e82d27 --- /dev/null +++ b/SharpMining/.gitignore @@ -0,0 +1,40 @@ +# Autosave files +*~ + +# build +[Oo]bj/ +[Bb]in/ +packages/ +TestResults/ + +# globs +Makefile.in +*.DS_Store +*.sln.cache +*.suo +*.cache +*.pidb +*.userprefs +*.usertasks +config.log +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.user +*.tar.gz +tarballs/ +test-results/ +Thumbs.db + +# Mac bundle stuff +*.dmg +*.app + +# resharper +*_Resharper.* +*.Resharper + +# dotCover +*.dotCover diff --git a/SharpMining/MiningJob.cs b/SharpMining/MiningJob.cs new file mode 100644 index 0000000..90c702b --- /dev/null +++ b/SharpMining/MiningJob.cs @@ -0,0 +1,50 @@ +using System; +using Newtonsoft.Json.Linq; +using sharp.extensions; +using sharp.cryptonote; +namespace SharpMining +{ + public class MiningJob + { + + public MiningJob(byte[] blob, UInt64 jobid, UInt64 height, UInt64 target) + { + this.Blob = blob; + this.JobID = jobid; + this.Height = height; + this.Target = target; + + Block block = new Block(blob); + + Console.WriteLine( block.ToString() ); + + } + + public byte[] Blob { get; private set; } + public UInt64 JobID { get; private set; } + public UInt64 Height { get; private set; } + public UInt64 Target { get; private set; } + public StratumConnection Miner { get; set; } + + public JToken toJSON() + { + JToken job = new JObject( + new JProperty("blob", HexString.toString(Blob)), + new JProperty("job_id", HexString.toString(JobID.GetBytes())), + new JProperty("target", HexString.toString(Target.GetBytes())) + ); + return job; + } + public JToken toJSON(UInt64 diff) + { + UInt64 target = (((UInt64)1<<32)-1) / diff; + JToken job = new JObject( + new JProperty("blob", Blob.Segment(0,76).toHexString()), + new JProperty("job_id", JobID.GetBytes().toHexString()), + new JProperty("target", target.GetBytes(Endianess.LittleEndian).toHexString().Substring(0,8)) + ); + return job; + } + + } +} diff --git a/SharpMining/MiningPool.cs b/SharpMining/MiningPool.cs new file mode 100644 index 0000000..26509f6 --- /dev/null +++ b/SharpMining/MiningPool.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using sharp.cryptonote.rpc; +using sharp.cryptonote; +using Newtonsoft.Json.Linq; +namespace SharpMining +{ + public class MiningPool + { + JToken poolConfig; + List daemons; + + public Daemon[] Daemons { get { return this.daemons.ToArray(); } } + public WorkManager WorkManager { get; private set; } + public CryptoNoteAddress PoolWallet { get; private set; } + public Dictionary assignedStratums; + + public MiningPool(JToken poolConfig) + { + this.poolConfig = poolConfig; + + this.daemons = new List(); + this.assignedStratums = new Dictionary(); + + this.Coin = (CryptoNoteCoin)Enum.Parse(typeof(CryptoNoteCoin), poolConfig["pool"]["coin"].ToObject()); + this.PoolWallet = new CryptoNoteAddress(poolConfig["pool"]["wallet"].ToObject()); + + this.WorkManager = new WorkManager(this); + + CreateDaemonRPC(); + } + + public CryptoNoteCoin Coin { get; private set; } + + + public void CreateDaemonRPC() + { + + foreach (JToken dc in poolConfig["daemons"]) + { + Daemon daemon = new Daemon(dc["host"].ToString(), dc["port"].ToObject()); + daemons.Add(daemon); + } + + } + + + public Daemon getCheckedDaemon() + { + foreach (Daemon daemon in this.daemons) + { + if (daemon.check()) + { + return daemon; + } + } + return null; + } + + public override string ToString() + { + return string.Format("[MiningPool: Coin={0}, PoolWallet={1}]", Coin, PoolWallet); + } + + + } + +} diff --git a/SharpMining/README.md b/SharpMining/README.md new file mode 100644 index 0000000..93e64be --- /dev/null +++ b/SharpMining/README.md @@ -0,0 +1,5 @@ +# SharpMining +Mono/.NET Implementation of Monero Mining Pool + +more information to come... + diff --git a/SharpMining/SharpMining.cs b/SharpMining/SharpMining.cs new file mode 100644 index 0000000..771dd4c --- /dev/null +++ b/SharpMining/SharpMining.cs @@ -0,0 +1,102 @@ +using System; +using sharp.cryptonote.rpc; +using sharp.cryptonote; +using Newtonsoft.Json.Linq; +using System.IO; +using System.Collections.Generic; +using System.Linq; + + +namespace SharpMining +{ + public class SharpMining + { + public static void Main(String[] args) + { + if (args.Length > 1){ + Console.WriteLine("usage: SharpMining.exe "); + return; + } + + SharpMining sm = new SharpMining(args); + sm.Run(); + } + + private String configFileName; + private JToken config; + + private List pools; + private List stratums; + + public SharpMining(String[] args){ + if (args.Length == 0){ + configFileName = "sharpmining.json"; + } else if (args.Length == 1){ + configFileName = args[0]; + }; + this.config = JToken.Parse(File.ReadAllText(configFileName)); + this.pools = new List(); + this.stratums = new List(); + } + + public void Run(){ + CreatePools(); + CreateStratums(); + + foreach (MiningPool pool in this.pools){ + Console.WriteLine("Running Pool for {0} with Pool-Wallet {1}",pool.Coin,pool.PoolWallet.ToString()); + } + + foreach (StratumListener l in this.stratums){ + Console.WriteLine("Started Stratum Listener [{0}] for Pools:",l.LocalEndpoint.ToString()); + foreach(MiningPool pool in l.AssociatedPools){ + Console.WriteLine(" -> {0}", pool.ToString()); + } + } + + + } + + public StratumListener[] Stratums { get { return this.stratums.ToArray(); } } + + public void CreatePools(){ + foreach (JToken pool in config["pools"]) + { + this.pools.Add(new MiningPool(pool)); + } + } + + public void CreateStratums(){ + + foreach (JToken dc in config["stratums"]){ + StratumListener stratum = new StratumListener(dc); + + if (dc["coins"].Equals(JValue.CreateNull())){ + foreach (MiningPool p in this.pools){ + stratum.associatePool(p); + } + } else { + foreach (JToken c in dc["coins"]){ + CryptoNoteCoin coin = c.ToObject(); + stratum.associatePool( findPool(coin) ); + } + } + + stratums.Add(stratum); + stratum.Start(); + } + + } + + public MiningPool findPool(CryptoNoteCoin coin){ + foreach (MiningPool p in this.pools){ + if (p.Coin.Equals(coin)){ + return p; + } + } + return null; + } + + + } +} diff --git a/SharpMining/SharpMining.csproj b/SharpMining/SharpMining.csproj new file mode 100644 index 0000000..910a0c2 --- /dev/null +++ b/SharpMining/SharpMining.csproj @@ -0,0 +1,76 @@ + + + + Debug + x86 + {5AE4E72A-253B-4FBD-AD5E-C038D57571D0} + Exe + SharpMining + SharpMining + v4.5 + + + true + full + true + bin\Debug + DEBUG; + prompt + 4 + x86 + + + true + bin\Release + prompt + 4 + x86 + + + + + + + + + + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + + + + + + + + PreserveNewest + + + + + + {DCE6066E-9709-4D12-8994-F7879C3557D6} + sharp.jsonrpc + + + {52C68C13-2DC2-438A-9EC1-E8C4953B07DF} + sharp.cryptonote + + + {97CA3CA9-98B3-4492-B072-D7A5995B68E9} + sharp.extensions + + + + + + + + + + + + + \ No newline at end of file diff --git a/SharpMining/StratumConnection.cs b/SharpMining/StratumConnection.cs new file mode 100644 index 0000000..3dfeca9 --- /dev/null +++ b/SharpMining/StratumConnection.cs @@ -0,0 +1,188 @@ +using System; +using System.Net.Sockets; +using System.Threading; +using System.IO; +using sharp.jsonrpc.net; +using Newtonsoft.Json.Linq; +using sharp.cryptonote; + +namespace SharpMining +{ + public class StratumConnection : JSONClient + { + delegate void threadsyncdelegate(); + + StratumListener listener; + Thread thread; + bool shouldExit; + + public Guid UID { get; } = Guid.NewGuid(); + + public CryptoNoteAddress Wallet { get; set; } + public string WorkerID { get; set; } + public int FixedDiff { get; set; } + public string Agent { get; set; } + + public MiningPool Pool { get; private set; } + + public MiningJob CurrentJob { get; private set; } + public MiningJob LastJob { get; private set; } + + public StratumConnection(StratumListener listener,Socket socket) + :base(socket) + { + this.listener = listener; + this.thread = new Thread(()=>run()); + this.thread.Start(); + } + + public new void Close(){ + Monitor.Enter(this); + if (shouldExit){ + return; + } + shouldExit = true; + Monitor.Wait(this); + + base.Close(); + + Monitor.Exit(this); + } + + private void run(){ + + while (!ShouldExit){ + try + { + JToken token = readJSON(); + + if (token["method"] != null) + { + methodCalled(token["method"].ToObject(), token["id"].ToObject(), token["params"]); + } + } catch (IOException ioe){ + Close(); + } catch (Exception e){ + Console.WriteLine("StratumConnection: [{0}] Exception: {1}",UID.ToString(),e.ToString()); + } + + } + + if (Pool != null){ + Pool.WorkManager.OnNewBlockAvailable -= WorkManager_OnNewBlockAvailable; + } + + Monitor.Enter(this); + Monitor.PulseAll(this); + Monitor.Exit(this); + } + + private bool ShouldExit { get { Monitor.Enter(this); bool se = this.shouldExit; Monitor.Exit(this); return se; } } + + private new void writeJSON(JToken token){ + Monitor.Enter(this); + base.writeJSON(token); + Monitor.Exit(this); + } + + private void methodCalled(string method,UInt64 id,JToken args){ + switch (method){ + case "login": + rpcLogin(id,args); + break; + case "submit": + rpcSubmit(id, args); + break; + default: + writeJSONRPC(id, null, new JValue(String.Format("Method not implemented: {0}", method))); + break; + } + } + + private string splitSuffix(char deli, ref string line) + { + return splitSuffix(deli, ref line, ""); + } + private string splitSuffix(char deli, ref string line, string def){ + string result = def; + int i = line.IndexOf(deli); + if (i >= 0){ + result = line.Substring(i + 1); + line = line.Substring(0, i); + }; + return result; + } + + private void rpcLogin(UInt64 id,JToken args){ + string username, passwd; + + Agent = args["agent"].ToObject(); + + username = args["login"].ToObject(); + passwd = args["pass"].ToObject(); + + try { + FixedDiff = int.Parse(splitSuffix('@', ref username,"0")); + WorkerID = splitSuffix('.', ref username); + Wallet = new CryptoNoteAddress(username); + + Pool = this.listener.getAssociatedPool(Wallet.CryptoNoteCoin); + + if (Pool == null){ + throw new Exception("No Pool for that coin available!"); + } + + MiningJob job = Pool.WorkManager.createJob(); + assignJob(job, false); + + Pool.WorkManager.OnNewBlockAvailable += WorkManager_OnNewBlockAvailable; + + } catch (Exception e){ + writeJSONRPC(id,null,new JValue(String.Format("An Exception occured ({0}: {1})",e.ToString(),e.Message))); + Close(); + } + + Console.WriteLine("Miner connected: [{3}] Wallet: {0} WorkerID: {1} FixedDiff: {2}", Wallet, WorkerID, FixedDiff, UID.ToString()); + + + writeJSONRPC(id, new JObject( + new JProperty("id", "555"), + new JProperty("job", CurrentJob.toJSON(100)) + ), null); + } + + private void rpcSubmit(UInt64 id,JToken args) + { + } + + private bool assignJob(MiningJob job,bool transmit){ + LastJob = CurrentJob; + CurrentJob = job; + + if (transmit){ + transmitCurrentJob(); + } + + return true; + } + + public void transmitCurrentJob(){ + writeJSON(new JObject( + new JProperty("jsonrpc", "2.0"), + new JProperty("method","job"), + new JProperty("params", CurrentJob.toJSON()) + )); + } + + void WorkManager_OnNewBlockAvailable(WorkManager workmanager) + { + assignJob( this.Pool.WorkManager.createJob(), true ); + } + + public override string ToString() + { + return string.Format("[StratumConnection: [{4}] MinerWallet={0}, WorkerID={1}, FixedDiff={2}, Agent={3}]", Wallet, WorkerID, FixedDiff, Agent, UID.ToString()); + } + + } +} diff --git a/SharpMining/StratumListener.cs b/SharpMining/StratumListener.cs new file mode 100644 index 0000000..e7e0715 --- /dev/null +++ b/SharpMining/StratumListener.cs @@ -0,0 +1,130 @@ +using System; +using System.Net; +using System.Collections.Generic; +using System.Threading; +using System.Net.Sockets; +using sharp.cryptonote; +using Newtonsoft.Json.Linq; +namespace SharpMining +{ + public delegate void StratumConnectionAccepted(StratumListener listener, StratumConnection stratumConnection); + + public class StratumListener : TcpListener + { + bool shouldExit; + List connections; + Thread thread; + + Dictionary associatedPools; + + public event StratumConnectionAccepted OnConnectionAccepted; + + public StratumListener(IPEndPoint endpoint) + :base(endpoint) + { + this.initialize(); + } + + public StratumListener(IPAddress bind,int port) + :base(bind,port) + { + this.initialize(); + } + + public StratumListener(string bind, int port) + :base(IPAddress.Parse(bind),port) + { + this.initialize(); + } + + public StratumListener(JToken stratumConfig) + :base(IPAddress.Parse(stratumConfig["bind"].ToString()),stratumConfig["port"].ToObject()) + { + this.initialize(); + } + + private void initialize(){ + this.associatedPools = new Dictionary(); + this.connections = new List(); + } + + public new void Start(){ + if (thread == null){ + thread = new Thread(() => run()); + thread.Start(); + } + } + + public new void Stop(){ + Monitor.Enter(this); + shouldExit = true; + Monitor.Wait(this); + Monitor.Exit(this); + } + + protected void ConnectionAccepted(StratumConnection connection){ + if (OnConnectionAccepted != null){ + OnConnectionAccepted(this,connection); + } + } + + private void run(){ + base.Start(5); + + while (!ShouldExit){ + StratumConnection connection = AcceptStratumConnection(); + + connection.OnConnectionClosed += (sender) => { removeConnection(connection); }; + + this.connections.Add(connection); + ConnectionAccepted(connection); + } + + base.Stop(); + + Monitor.Enter(this); + this.thread = null; + + foreach (StratumConnection c in this.connections){ + c.Close(); + } + + Monitor.PulseAll(this); + Monitor.Exit(this); + } + + public StratumConnection AcceptStratumConnection(){ + return new StratumConnection(this,this.AcceptSocket()); + } + + private void removeConnection(StratumConnection connection){ + this.connections.Remove(connection); + Console.WriteLine("StratumConnection lost: {0}",connection); + } + + + private bool ShouldExit { get { Monitor.Enter(this); bool se = this.shouldExit; Monitor.Exit(this); return se; } } + + public StratumConnection[] Connections { get { return this.connections.ToArray(); } } + + public MiningPool[] AssociatedPools { + get { + MiningPool[] pools = new MiningPool[this.associatedPools.Count]; + this.associatedPools.Values.CopyTo(pools,0); + return pools; + } + } + + public MiningPool getAssociatedPool(CryptoNoteCoin coin){ + if (!this.associatedPools.ContainsKey(coin)){ + return null; + } + return this.associatedPools[coin]; + } + + public void associatePool(MiningPool pool){ + this.associatedPools[pool.Coin] = pool; + } + + } +} diff --git a/SharpMining/WorkManager.cs b/SharpMining/WorkManager.cs new file mode 100644 index 0000000..22c8920 --- /dev/null +++ b/SharpMining/WorkManager.cs @@ -0,0 +1,92 @@ +using System; +using System.Threading; +using sharp.cryptonote; +using sharp.cryptonote.rpc; +using System.Collections.Generic; +using sharp.extensions; +using Newtonsoft.Json.Linq; + +namespace SharpMining +{ + public delegate void NewBlockAvailable(WorkManager workmanager); + + public class WorkManager + { + Thread thread; + + BlockTemplate currentTemplate; + + UInt64 nextJobID; + Dictionary currentJobs; + + public event NewBlockAvailable OnNewBlockAvailable; + public MiningPool MiningPool { get; private set; } + + public WorkManager(MiningPool pool) + { + this.MiningPool = pool; + + this.nextJobID = 1; + this.currentJobs = new Dictionary(); + + this.thread = new Thread(() => Run()); + this.thread.Start(); + } + + private void Run(){ + while (true){ + Thread.Sleep(2000); + + Daemon daemon = MiningPool.getCheckedDaemon(); + if (daemon == null){ + Console.WriteLine("WorkManager: no Daemon available"); + } else { + BlockTemplate newTemplate = daemon.getBlockTemplate(MiningPool.PoolWallet, 8); + Console.WriteLine("current target height is {0}",newTemplate.Height); + + if ((currentTemplate == null) || (currentTemplate.Height != newTemplate.Height)){ + changeCurrentBlock(newTemplate); + } + } + + } + } + + private void fireNewBlockAvailable(){ + if (OnNewBlockAvailable != null){ + OnNewBlockAvailable.Invoke(this); + } + } + + public void changeCurrentBlock(BlockTemplate blockTemplate){ + Monitor.Enter(this); + + currentTemplate = blockTemplate; + Console.WriteLine("new block target height: {0} target difficulty: {1} [0x{1:x}]",blockTemplate.Height,blockTemplate.Difficulty); + + fireNewBlockAvailable(); + + Monitor.Exit(this); + } + + public MiningJob createJob() + { + Monitor.Enter(this); + + if (this.currentTemplate == null){ + return null; + } + + UInt64 jobid = this.nextJobID++; + MiningJob job = new MiningJob(this.currentTemplate.generateJobTemplate(jobid.GetBytes()), jobid, this.currentTemplate.Height, this.currentTemplate.Difficulty); + this.currentJobs.Add(jobid, job); + + Monitor.Exit(this); + + return job; + } + + + + } +} diff --git a/SharpMining/daemon.cs b/SharpMining/daemon.cs new file mode 100644 index 0000000..517c39e --- /dev/null +++ b/SharpMining/daemon.cs @@ -0,0 +1,10 @@ +using System; +namespace SharpMining +{ + public class daemon + { + public daemon() + { + } + } +} diff --git a/SharpMining/packages.config b/SharpMining/packages.config new file mode 100644 index 0000000..e157ba1 --- /dev/null +++ b/SharpMining/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/SharpMining/sharpmining.json b/SharpMining/sharpmining.json new file mode 100644 index 0000000..230fed2 --- /dev/null +++ b/SharpMining/sharpmining.json @@ -0,0 +1,52 @@ +{ + pools : [ + { + pool: { + coin: "XMR", + wallet: "45YKUs6Lr8562D1vwUfVGPZR7RZp4vqnL95XMvZJEnjREiwEjs8RscC8Djxg5jRzbDAnbK6A9Z9M9VTeMjn9EG1D4Ly7U4i" + }, + + daemons: [ + { host: "10.0.0.1", port: 18081 } + ], + + wallets: [ + { host: "10.0.0.1", port: 8082 }, + ], + + rpc: { + bind: "127.0.0.1", + port: "8880" + }, + + contact: "info@lupus-nobilis.de" + }, + { + pool: { + coin: "AEON", + wallet: "WmtVdqr4fqH3YuwoasjChqhmF3pv8pQ3JgQTKSaA2Bog5zFkporDmyK59fAgbdZjCMcv38wzBk4ZogMYkwyKwH1337FBF2AaQ" + }, + + daemons: [ + { host: "10.0.0.1", port: 11181 } + ], + + wallets: [ + { host: "10.0.0.1", port: 8082 }, + ], + + rpc: { + bind: "127.0.0.1", + port: "8881" + }, + + contact: "info@lupus-nobilis.de" + } + ], + + stratums: [ + { bind: "127.0.0.1", port: 3333, diff: 100, description: "Stratum Port for Low-End Miner", coins: null }, + { bind: "127.0.0.1", port: 5555, diff: 1000, description: "Stratum Port for Mid-Range Miner", coins: null }, + { bind: "127.0.0.1", port: 7777, diff: 10000, description: "Stratum Port for High-End Miner", coins: [ "XMR" ] } + ] +} \ No newline at end of file