Esempio n. 1
0
        override protected void Authorize()
        {
            try  { mMutex.WaitOne(5000); } catch (Exception) { }
            WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(new Dictionary <string, Object> {
                { "id", mJsonRPCMessageID++ },
                { "jsonrpc", "2.0" },
                { "method", "eth_submitLogin" },
                { "params", new List <string> {
                      Username
                  } }
            }));
            try { mMutex.ReleaseMutex(); } catch (Exception) { }

            try {
                var response = JsonConvert.DeserializeObject <Dictionary <string, Object> >(ReadLine());
                if (response["result"] == null)
                {
                    throw (UnrecoverableException = new UnrecoverableException("Authorization failed."));
                }
            } catch (Exception) {
                throw this.UnrecoverableException = new UnrecoverableException("Authorization failed.");
            }

            try { mMutex.WaitOne(5000); } catch (Exception) { }
            WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(new Dictionary <string, Object> {
                { "id", mJsonRPCMessageID++ },
                { "jsonrpc", "2.0" },
                { "method", "eth_getWork" }
            }));
            try  { mMutex.ReleaseMutex(); } catch (Exception) { }

            mPingThread = new Thread(new ThreadStart(PingThread));
            mPingThread.IsBackground = true;
            mPingThread.Start();
        }
Esempio n. 2
0
        public void Connect()
        {
            try {
                if (Stopped)
                {
                    return;
                }

                MainForm.Logger("Connecting to " + ServerAddress + ":" + ServerPort + " as " + Username + "...");

                try { mMutex.WaitOne(5000); } catch (Exception) { }

                UnrecoverableException = null;
                mClient       = new TcpClient(ServerAddress, ServerPort);
                mStream       = mClient.GetStream();
                mStreamReader = new StreamReader(mStream, System.Text.Encoding.ASCII, false);
                mStreamWriter = new StreamWriter(mStream, System.Text.Encoding.ASCII);

                try { mMutex.ReleaseMutex(); } catch (Exception) { }

                Authorize();

                mStreamReaderThread = new Thread(new ThreadStart(StreamReaderThread));
                mStreamReaderThread.IsBackground = true;
                mStreamReaderThread.Start();
            } catch (Exception ex) {
                MainForm.Logger("Exception in Stratum.Connect(): " + ex.ToString());
            }
        }
Esempio n. 3
0
        override protected void Authorize()
        {
            try  { mMutex.WaitOne(5000); } catch (Exception) { }

            mJsonRPCMessageID = 1;

            WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(new Dictionary <string, Object> {
                { "id", mJsonRPCMessageID++ },
                { "method", "mining.subscribe" },
                { "params", new List <string> {
                      MainForm.shortAppName + "/" + MainForm.appVersion,
                      "EthereumStratum/1.0.0"
                  } }
            }));

            Dictionary <String, Object> response;

            try {
                response        = JsonConvert.DeserializeObject <Dictionary <string, Object> >(ReadLine());
                mSubsciptionID  = (string)(((JArray)(((JArray)(response["result"]))[0]))[1]);
                mPoolExtranonce = (string)(((JArray)(response["result"]))[1]);
            } catch (Exception) {
                throw this.UnrecoverableException = new UnrecoverableException("Authorization failed.");
            }

            // mining.extranonce.subscribe
            WriteLine(JsonConvert.SerializeObject(new Dictionary <string, Object> {
                { "id", mJsonRPCMessageID++ },
                { "method", "mining.extranonce.subscribe" },
                { "params", new List <string> {
                  } }
            }));
            try {
                response = JsonConvert.DeserializeObject <Dictionary <string, Object> >(ReadLine());
            } catch (Exception) {
                throw this.UnrecoverableException = new UnrecoverableException("Authorization failed.");
            }
            //MainForm.Logger("mining.extranonce.subscribe: " + response["result"]); // TODO

            WriteLine(JsonConvert.SerializeObject(new Dictionary <string, Object> {
                { "id", mJsonRPCMessageID++ },
                { "method", "mining.authorize" },
                { "params", new List <string> {
                      Username,
                      Password
                  } }
            }));
            response = JsonConvert.DeserializeObject <Dictionary <string, Object> >(ReadLine());
            if (!(bool)response["result"])
            {
                try  { mMutex.ReleaseMutex(); } catch (Exception) { }
                throw (UnrecoverableException = new UnrecoverableException("Authorization failed."));
            }

            try  { mMutex.ReleaseMutex(); } catch (Exception) { }
        }
Esempio n. 4
0
        public void Start()
        {
            mStopped = false;
            mDone    = false;
            UnrecoverableException = null;

            MarkAsAlive();
            mMinerThread = new System.Threading.Thread(MinerThread);
            mMinerThread.IsBackground = true;
            mMinerThread.Start();
        }
Esempio n. 5
0
        override unsafe protected void MinerThread()
        {
            Random r = new Random();

            UInt32[] ethashOutput     = new UInt32[256];
            byte[]   ethashHeaderhash = new byte[32];

            MarkAsAlive();

            MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");

            BuildEthashProgram();

            fixed(UInt32 *ethashOutputPtr = ethashOutput)
            fixed(byte *ethashHeaderhashPtr = ethashHeaderhash)
            fixed(byte *pascalMidstatePtr   = mPascalMidstate)
            fixed(byte *pascalInputPtr      = mPascalInput)
            fixed(UInt32 * pascalOutputPtr  = mPascalOutput)
            while (!Stopped)
            {
                MarkAsAlive();

                try
                {
                    int  ethashEpoch   = -1;
                    long ethashDAGSize = 0;
                    ComputeBuffer <byte> ethashDAGBuffer = null;

                    mEthashSearchKernel.SetMemoryArgument(7 + 0, mPascalInputBuffer);
                    mEthashSearchKernel.SetMemoryArgument(7 + 1, mPascalOutputBuffer);
                    mEthashSearchKernel.SetMemoryArgument(7 + 4, mPascalMidstateBuffer);
                    mEthashSearchKernel.SetValueArgument <UInt32>(7 + 5, mPascalRatio);

                    // Wait for the first job to arrive.
                    int elapsedTime = 0;
                    while ((mEthashStratum == null || mEthashStratum.GetJob() == null || mPascalStratum == null || mPascalStratum.GetJob() == null) && elapsedTime < 60000)
                    {
                        Thread.Sleep(100);
                        elapsedTime += 100;
                    }
                    if (mEthashStratum == null || mEthashStratum.GetJob() == null || mPascalStratum == null || mPascalStratum.GetJob() == null)
                    {
                        MainForm.Logger("Ethash stratum server failed to send a new job.");
                        //throw new TimeoutException("Stratum server failed to send a new job.");
                        return;
                    }

                    System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                    EthashStratum.Work           ethashWork;
                    PascalStratum.Work           pascalWork;

                    while (!Stopped && (ethashWork = mEthashStratum.GetWork()) != null && (pascalWork = mPascalStratum.GetWork()) != null)
                    {
                        MarkAsAlive();

                        String ethashPoolExtranonce      = mEthashStratum.PoolExtranonce;
                        byte[] ethashExtranonceByteArray = Utilities.StringToByteArray(ethashPoolExtranonce);
                        byte   ethashLocalExtranonce     = (byte)ethashWork.LocalExtranonce;
                        UInt64 ethashStartNonce          = (UInt64)ethashLocalExtranonce << (8 * (7 - ethashExtranonceByteArray.Length));
                        for (int i = 0; i < ethashExtranonceByteArray.Length; ++i)
                        {
                            ethashStartNonce |= (UInt64)ethashExtranonceByteArray[i] << (8 * (7 - i));
                        }
                        ethashStartNonce += (ulong)r.Next(0, int.MaxValue) & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8));
                        String ethashJobID      = ethashWork.GetJob().ID;
                        String ethashSeedhash   = ethashWork.GetJob().Seedhash;
                        double ethashDifficulty = mEthashStratum.Difficulty;
                        Buffer.BlockCopy(Utilities.StringToByteArray(ethashWork.GetJob().Headerhash), 0, ethashHeaderhash, 0, 32);
                        Queue.Write <byte>(mEthashHeaderBuffer, true, 0, 32, (IntPtr)ethashHeaderhashPtr, null);

                        var pascalJob = pascalWork.Job;
                        Array.Copy(pascalWork.Blob, mPascalInput, sPascalInputSize);
                        CalculatePascalMidState();
                        Queue.Write <byte>(mPascalMidstateBuffer, true, 0, sPascalMidstateSize, (IntPtr)pascalMidstatePtr, null);
                        UInt32 pascalStartNonce = (UInt32)(r.Next(0, int.MaxValue));
                        UInt64 PascalTarget     = (UInt64)((double)0xffff0000UL / mPascalStratum.Difficulty);
                        mEthashSearchKernel.SetValueArgument <UInt64>(7 + 3, PascalTarget);
                        Queue.Write <byte>(mPascalInputBuffer, true, 0, sPascalInputSize, (IntPtr)pascalInputPtr, null);

                        if (ethashEpoch != ethashWork.GetJob().Epoch)
                        {
                            if (ethashDAGBuffer != null)
                            {
                                ethashDAGBuffer.Dispose();
                                ethashDAGBuffer = null;
                            }
                            ethashEpoch = ethashWork.GetJob().Epoch;
                            DAGCache cache = new DAGCache(ethashEpoch, ethashWork.GetJob().Seedhash);
                            ethashDAGSize = Utilities.GetDAGSize(ethashEpoch);

                            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                            sw.Start();
                            mEthashGlobalWorkSizeArray[0]  = ethashDAGSize / 64;
                            mEthashGlobalWorkSizeArray[0] /= 8;
                            if (mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0] > 0)
                            {
                                mEthashGlobalWorkSizeArray[0] += mEthashLocalWorkSizeArray[0] - mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0];
                            }

                            ComputeBuffer <byte> DAGCacheBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, cache.GetData().Length);

                            fixed(byte *p = cache.GetData())
                            Queue.Write <byte>(DAGCacheBuffer, true, 0, cache.GetData().Length, (IntPtr)p, null);

                            ethashDAGBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadWrite, mEthashGlobalWorkSizeArray[0] * 8 * 64 /* ethashDAGSize */); // With this, we can remove a conditional statement in the DAG kernel.

                            mEthashDAGKernel.SetValueArgument <UInt32>(0, 0);
                            mEthashDAGKernel.SetMemoryArgument(1, DAGCacheBuffer);
                            mEthashDAGKernel.SetMemoryArgument(2, ethashDAGBuffer);
                            mEthashDAGKernel.SetValueArgument <UInt32>(3, (UInt32)cache.GetData().Length / 64);
                            mEthashDAGKernel.SetValueArgument <UInt32>(4, 0xffffffffu);

                            for (long start = 0; start < ethashDAGSize / 64; start += mEthashGlobalWorkSizeArray[0])
                            {
                                mEthashGlobalWorkOffsetArray[0] = start;
                                Queue.Execute(mEthashDAGKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null);
                                Queue.Finish();
                                if (Stopped || !mEthashStratum.GetJob().ID.Equals(ethashJobID))
                                {
                                    break;
                                }
                            }
                            DAGCacheBuffer.Dispose();
                            if (Stopped || !mEthashStratum.GetJob().ID.Equals(ethashJobID))
                            {
                                break;
                            }
                            sw.Stop();
                            MainForm.Logger("Generated DAG for Epoch #" + ethashEpoch + " (" + (long)sw.Elapsed.TotalMilliseconds + "ms).");
                        }

                        consoleUpdateStopwatch.Start();

                        while (!Stopped && mEthashStratum.GetJob().ID.Equals(ethashJobID) && mEthashStratum.PoolExtranonce.Equals(ethashPoolExtranonce) && mPascalStratum.GetJob().Equals(pascalJob))
                        {
                            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                            sw.Start();

                            MarkAsAlive();

                            // Get a new local extranonce if necessary.
                            if ((ethashStartNonce & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8)) + (ulong)mEthashGlobalWorkSizeArray[0] * 3 / 4) >= ((ulong)0x1 << (64 - (ethashExtranonceByteArray.Length * 8 + 8))))
                            {
                                break;
                            }
                            if (0xffffffffu - pascalStartNonce < (UInt32)mEthashGlobalWorkSizeArray[0] * mPascalRatio)
                            {
                                break;
                            }

                            UInt64 target = (UInt64)((double)0xffff0000U / ethashDifficulty);
                            mEthashSearchKernel.SetMemoryArgument(0, mEthashOutputBuffer);                   // g_output
                            mEthashSearchKernel.SetMemoryArgument(1, mEthashHeaderBuffer);                   // g_header
                            mEthashSearchKernel.SetMemoryArgument(2, ethashDAGBuffer);                       // _g_dag
                            mEthashSearchKernel.SetValueArgument <UInt32>(3, (UInt32)(ethashDAGSize / 128)); // DAG_SIZE
                            mEthashSearchKernel.SetValueArgument <UInt64>(4, ethashStartNonce);              // start_nonce
                            mEthashSearchKernel.SetValueArgument <UInt64>(5, target);                        // target
                            mEthashSearchKernel.SetValueArgument <UInt32>(6, 0xffffffffu);                   // isolate

                            mEthashSearchKernel.SetValueArgument <UInt32>(7 + 2, pascalStartNonce);

                            ethashOutput[255] = 0; // ethashOutput[255] is used as an atomic counter.
                            Queue.Write <UInt32>(mEthashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null);
                            mEthashGlobalWorkOffsetArray[0] = 0;
                            mPascalOutput[255] = 0; // mPascalOutput[255] is used as an atomic counter.
                            Queue.Write <UInt32>(mPascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null);
                            Queue.Execute(mEthashSearchKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null);

                            Queue.Read <UInt32>(mEthashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null);
                            if (mEthashStratum.GetJob().ID.Equals(ethashJobID))
                            {
                                for (int i = 0; i < ethashOutput[255]; ++i)
                                {
                                    mEthashStratum.Submit(GatelessGateDevice, ethashWork.GetJob(), ethashStartNonce + (UInt64)ethashOutput[i]);
                                }
                            }
                            ethashStartNonce += (UInt64)mEthashGlobalWorkSizeArray[0] * 3 / 4;

                            Queue.Read <UInt32>(mPascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null);
                            if (mPascalStratum.GetJob().Equals(pascalJob))
                            {
                                for (int i = 0; i < mPascalOutput[255]; ++i)
                                {
                                    mPascalStratum.Submit(GatelessGateDevice, pascalWork, mPascalOutput[i]);
                                }
                            }
                            pascalStartNonce += (UInt32)mEthashGlobalWorkSizeArray[0] * mPascalRatio;

                            sw.Stop();
                            Speed       = ((double)mEthashGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds * 0.75;
                            SecondSpeed = ((double)mEthashGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds * mPascalRatio;
                            if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                            {
                                MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Ethash), ", Speed / (1000000)) + String.Format("{0:N2} Mh/s (Pascal)", SecondSpeed / (1000000)));
                                consoleUpdateStopwatch.Restart();
                            }
                        }
                    }

                    if (ethashDAGBuffer != null)
                    {
                        ethashDAGBuffer.Dispose();
                        ethashDAGBuffer = null;
                    }
                } catch (Exception ex) {
                    MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                    Speed = 0;
                    if (UnrecoverableException.IsUnrecoverableException(ex))
                    {
                        this.UnrecoverableException = new UnrecoverableException(ex, GatelessGateDevice);
                        Stop();
                    }
                    else
                    {
                        MainForm.Logger("Restarting miner thread...");
                        System.Threading.Thread.Sleep(5000);
                    }
                }
            }

            MarkAsDone();
        }
        override unsafe protected void MinerThread()
        {
            Random r = new Random();

            MarkAsAlive();

            MainForm.Logger("Dual Ethash/Lbry miner thread for Device #" + DeviceIndex + " started.");

            BuildEthashProgram();

            fixed(UInt32 *ethashOutputPtr = mEthashOutput)
            fixed(byte *ethashHeaderhashPtr = mEthashHeaderhash)
            fixed(byte *lbryInputPtr        = mLbryInput)
            fixed(UInt32 * lbryOutputPtr    = mLbryOutput)
            while (!Stopped)
            {
                MarkAsAlive();

                try
                {
                    int  ethashEpoch   = -1;
                    long ethashDAGSize = 0;
                    ComputeBuffer <byte> ethashDAGBuffer = null;

                    // Wait for the first job to arrive.
                    int elapsedTime = 0;
                    while ((mEthashStratum == null || mEthashStratum.GetJob() == null || mLbryStratum == null || mLbryStratum.GetJob() == null) && elapsedTime < Parameters.TimeoutForFirstJobInMilliseconds && !Stopped)
                    {
                        Thread.Sleep(100);
                        elapsedTime += 100;
                    }
                    if (mEthashStratum == null || mEthashStratum.GetJob() == null || mLbryStratum == null || mLbryStratum.GetJob() == null)
                    {
                        MainForm.Logger("Stratum server failed to send a new job.");
                        return;
                    }

                    System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                    EthashStratum.Work           ethashWork;
                    LbryStratum.Work             lbryWork;

                    mEthashSearchKernel.SetMemoryArgument(7, mLbryInputBuffer);
                    mEthashSearchKernel.SetMemoryArgument(8, mLbryOutputBuffer);

                    while (!Stopped && (ethashWork = mEthashStratum.GetWork()) != null && (lbryWork = mLbryStratum.GetWork()) != null)
                    {
                        MarkAsAlive();

                        String ethashPoolExtranonce      = mEthashStratum.PoolExtranonce;
                        byte[] ethashExtranonceByteArray = Utilities.StringToByteArray(ethashPoolExtranonce);
                        byte   ethashLocalExtranonce     = (byte)ethashWork.LocalExtranonce;
                        UInt64 ethashStartNonce          = (UInt64)ethashLocalExtranonce << (8 * (7 - ethashExtranonceByteArray.Length));
                        for (int i = 0; i < ethashExtranonceByteArray.Length; ++i)
                        {
                            ethashStartNonce |= (UInt64)ethashExtranonceByteArray[i] << (8 * (7 - i));
                        }
                        ethashStartNonce += (ulong)r.Next(0, int.MaxValue) & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8));
                        String ethashJobID      = ethashWork.GetJob().ID;
                        String ethashSeedhash   = ethashWork.GetJob().Seedhash;
                        double ethashDifficulty = mEthashStratum.Difficulty;
                        Buffer.BlockCopy(Utilities.StringToByteArray(ethashWork.GetJob().Headerhash), 0, mEthashHeaderhash, 0, 32);
                        Queue.Write <byte>(mEthashHeaderBuffer, true, 0, 32, (IntPtr)ethashHeaderhashPtr, null);

                        var lbryJob = lbryWork.Job;
                        Array.Copy(lbryWork.Blob, mLbryInput, 112);
                        UInt32 lbryStartNonce = (UInt32)(r.Next(0, int.MaxValue));
                        UInt64 lbryTarget     = (UInt64)((double)0xffff0000UL / (mLbryStratum.Difficulty / 256));
                        mEthashSearchKernel.SetValueArgument <UInt64>(10, lbryTarget);
                        Queue.Write <byte>(mLbryInputBuffer, true, 0, 112, (IntPtr)lbryInputPtr, null);

                        if (ethashEpoch != ethashWork.GetJob().Epoch)
                        {
                            if (ethashDAGBuffer != null)
                            {
                                ethashDAGBuffer.Dispose();
                                ethashDAGBuffer = null;
                            }
                            ethashEpoch = ethashWork.GetJob().Epoch;
                            DAGCache cache = new DAGCache(ethashEpoch, ethashWork.GetJob().Seedhash);
                            ethashDAGSize = Utilities.GetDAGSize(ethashEpoch);

                            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                            sw.Start();
                            mEthashGlobalWorkSizeArray[0]  = ethashDAGSize / 64;
                            mEthashGlobalWorkSizeArray[0] /= 8;
                            if (mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0] > 0)
                            {
                                mEthashGlobalWorkSizeArray[0] += mEthashLocalWorkSizeArray[0] - mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0];
                            }

                            ComputeBuffer <byte> DAGCacheBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, cache.GetData().Length);

                            fixed(byte *p = cache.GetData())
                            Queue.Write <byte>(DAGCacheBuffer, true, 0, cache.GetData().Length, (IntPtr)p, null);

                            ethashDAGBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadWrite, mEthashGlobalWorkSizeArray[0] * 8 * 64 /* ethashDAGSize */); // With this, we can remove a conditional statement in the DAG kernel.

                            mEthashDAGKernel.SetValueArgument <UInt32>(0, 0);
                            mEthashDAGKernel.SetMemoryArgument(1, DAGCacheBuffer);
                            mEthashDAGKernel.SetMemoryArgument(2, ethashDAGBuffer);
                            mEthashDAGKernel.SetValueArgument <UInt32>(3, (UInt32)cache.GetData().Length / 64);
                            mEthashDAGKernel.SetValueArgument <UInt32>(4, 0xffffffffu);

                            for (long start = 0; start < ethashDAGSize / 64; start += mEthashGlobalWorkSizeArray[0])
                            {
                                mEthashGlobalWorkOffsetArray[0] = start;
                                Queue.Execute(mEthashDAGKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null);
                                Queue.Finish();
                                if (Stopped || !mEthashStratum.GetJob().ID.Equals(ethashJobID))
                                {
                                    break;
                                }
                            }
                            DAGCacheBuffer.Dispose();
                            if (Stopped || !mEthashStratum.GetJob().ID.Equals(ethashJobID))
                            {
                                break;
                            }
                            sw.Stop();
                            MainForm.Logger("Generated DAG for Epoch #" + ethashEpoch + " (" + (long)sw.Elapsed.TotalMilliseconds + "ms).");
                        }

                        consoleUpdateStopwatch.Start();

                        while (!Stopped && mEthashStratum.GetJob().ID.Equals(ethashJobID) && mEthashStratum.PoolExtranonce.Equals(ethashPoolExtranonce) && mLbryStratum.GetJob().Equals(lbryJob))
                        {
                            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                            sw.Start();

                            MarkAsAlive();

                            mEthashGlobalWorkOffsetArray[0] = 0;

                            mEthashSearchKernel.SetValueArgument <UInt32>(9, lbryStartNonce);;

                            // Get a new local extranonce if necessary.
                            if ((ethashStartNonce & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8)) + (ulong)mEthashGlobalWorkSizeArray[0] * 3 / 4) >= ((ulong)0x1 << (64 - (ethashExtranonceByteArray.Length * 8 + 8))))
                            {
                                break;
                            }
                            if (0xffffffffu - lbryStartNonce < (UInt32)mEthashGlobalWorkSizeArray[0] / 4)
                            {
                                break;
                            }

                            UInt64 target = (UInt64)((double)0xffff0000U / ethashDifficulty);
                            mEthashSearchKernel.SetMemoryArgument(0, mEthashOutputBuffer);                   // g_output
                            mEthashSearchKernel.SetMemoryArgument(1, mEthashHeaderBuffer);                   // g_header
                            mEthashSearchKernel.SetMemoryArgument(2, ethashDAGBuffer);                       // _g_dag
                            mEthashSearchKernel.SetValueArgument <UInt32>(3, (UInt32)(ethashDAGSize / 128)); // DAG_SIZE
                            mEthashSearchKernel.SetValueArgument <UInt64>(4, ethashStartNonce);              // start_nonce
                            mEthashSearchKernel.SetValueArgument <UInt64>(5, target);                        // target
                            mEthashSearchKernel.SetValueArgument <UInt32>(6, 0xffffffffu);                   // isolate
                            mEthashOutput[255] = 0;                                                          // mEthashOutput[255] is used as an atomic counter.
                            Queue.Write <UInt32>(mEthashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null);

                            mLbryOutput[255] = 0; // mLbryOutput[255] is used as an atomic counter.
                            Queue.Write <UInt32>(mLbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null);

                            Queue.Execute(mEthashSearchKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null);

                            Queue.Read <UInt32>(mEthashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null);
                            if (mEthashStratum.GetJob().ID.Equals(ethashJobID))
                            {
                                for (int i = 0; i < mEthashOutput[255]; ++i)
                                {
                                    mEthashStratum.Submit(Device, ethashWork.GetJob(), ethashStartNonce + (UInt64)mEthashOutput[i]);
                                }
                            }
                            ethashStartNonce += (UInt64)mEthashGlobalWorkSizeArray[0] * 3 / 4;

                            Queue.Read <UInt32>(mLbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null);
                            if (mLbryStratum.GetJob().Equals(lbryJob))
                            {
                                for (int i = 0; i < mLbryOutput[255]; ++i)
                                {
                                    String result = "";
                                    for (int j = 0; j < 8; ++j)
                                    {
                                        UInt32 word = mLbryOutput[256 + i * 8 + j];
                                        result += String.Format("{0:x2}{1:x2}{2:x2}{3:x2}", ((word >> 0) & 0xff), ((word >> 8) & 0xff), ((word >> 16) & 0xff), ((word >> 24) & 0xff));
                                    }
                                    mLbryStratum.Submit(Device, lbryWork, mLbryOutput[i], result);
                                }
                            }
                            lbryStartNonce += (UInt32)mEthashGlobalWorkSizeArray[0] / 4;

                            sw.Stop();
                            Speed = ((double)mEthashGlobalWorkSizeArray[0] * 3 / 4) / sw.Elapsed.TotalSeconds;
                            double speedSecondary = (((double)mEthashGlobalWorkSizeArray[0] / 4) / sw.Elapsed.TotalSeconds);
                            if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                            {
                                MainForm.Logger("Device #" + DeviceIndex + " (Ethash): " + String.Format("{0:N2} Mh/s (Ethash), {1:N2} Mh/s (Lbry)", Speed / (1000000), speedSecondary / (1000000)));
                                consoleUpdateStopwatch.Restart();
                            }
                        }
                    }

                    if (ethashDAGBuffer != null)
                    {
                        ethashDAGBuffer.Dispose();
                        ethashDAGBuffer = null;
                    }
                } catch (Exception ex) {
                    MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                    Speed = 0;
                    if (UnrecoverableException.IsUnrecoverableException(ex))
                    {
                        this.UnrecoverableException = new UnrecoverableException(ex, Device);
                        Stop();
                    }
                    else
                    {
                        MainForm.Logger("Restarting miner thread...");
                        System.Threading.Thread.Sleep(5000);
                    }
                }
            }

            MarkAsDone();
        }
        override unsafe protected void MinerThread()
        {
            ComputeProgram program = null;

            try {
                Random        r                = new Random();
                ComputeDevice computeDevice    = OpenCLDevice.GetComputeDevice();
                UInt32[]      ethashOutput     = new UInt32[256];
                byte[]        ethashHeaderhash = new byte[32];

                MarkAsAlive();

                MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");

                program = BuildProgram("ethash", mEthashLocalWorkSizeArray[0], "-O1", "", "");

                MemoryUsage = 256 + 32;

                using (var searchKernel = program.CreateKernel("search"))
                    using (var DAGKernel = program.CreateKernel("GenerateDAG"))
                        using (var ethashOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, 256))
                            using (var ethashHeaderBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, 32))
                                fixed(UInt32 *ethashOutputPtr = ethashOutput)
                                fixed(byte *ethashHeaderhashPtr = ethashHeaderhash)
                                while (!Stopped)
                                {
                                    ComputeBuffer <byte> ethashDAGBuffer = null;

                                    MarkAsAlive();

                                    try
                                    {
                                        int  ethashEpoch   = -1;
                                        long ethashDAGSize = 0;

                                        // Wait for the first job to arrive.
                                        int elapsedTime = 0;
                                        while ((Stratum == null || Stratum.GetJob() == null) && elapsedTime < Parameters.TimeoutForFirstJobInMilliseconds && !Stopped)
                                        {
                                            Thread.Sleep(100);
                                            elapsedTime += 100;
                                        }
                                        if (Stratum == null || Stratum.GetJob() == null)
                                        {
                                            MainForm.Logger("Ethash stratum server failed to send a new job.");
                                            //throw new TimeoutException("Stratum server failed to send a new job.");
                                            return;
                                        }

                                        System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                                        EthashStratum.Work           ethashWork;
                                        EthashStratum.Job            ethashJob;

                                        while (!Stopped && (ethashWork = Stratum.GetWork()) != null && (ethashJob = ethashWork.GetJob()) != null)
                                        {
                                            MarkAsAlive();

                                            String ethashPoolExtranonce      = Stratum.PoolExtranonce;
                                            byte[] ethashExtranonceByteArray = Utilities.StringToByteArray(ethashPoolExtranonce);
                                            byte   ethashLocalExtranonce     = (byte)ethashWork.LocalExtranonce;
                                            UInt64 ethashStartNonce          = (UInt64)ethashLocalExtranonce << (8 * (7 - ethashExtranonceByteArray.Length));
                                            for (int i = 0; i < ethashExtranonceByteArray.Length; ++i)
                                            {
                                                ethashStartNonce |= (UInt64)ethashExtranonceByteArray[i] << (8 * (7 - i));
                                            }
                                            ethashStartNonce += (ulong)r.Next(0, int.MaxValue) & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8));
                                            String ethashJobID      = ethashJob.ID;
                                            String ethashSeedhash   = ethashJob.Seedhash;
                                            double ethashDifficulty = Stratum.Difficulty;

                                            Buffer.BlockCopy(Utilities.StringToByteArray(ethashWork.GetJob().Headerhash), 0, ethashHeaderhash, 0, 32);
                                            Queue.Write <byte>(ethashHeaderBuffer, true, 0, 32, (IntPtr)ethashHeaderhashPtr, null);

                                            if (ethashEpoch != ethashWork.GetJob().Epoch)
                                            {
                                                if (ethashDAGBuffer != null)
                                                {
                                                    MemoryUsage -= ethashDAGBuffer.Size;
                                                    ethashDAGBuffer.Dispose();
                                                    ethashDAGBuffer = null;
                                                }
                                                ethashEpoch = ethashWork.GetJob().Epoch;
                                                DAGCache cache = new DAGCache(ethashEpoch, ethashWork.GetJob().Seedhash);
                                                ethashDAGSize = Utilities.GetDAGSize(ethashEpoch);

                                                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                                                sw.Start();
                                                mEthashGlobalWorkSizeArray[0]  = ethashDAGSize / 64;
                                                mEthashGlobalWorkSizeArray[0] /= 8;
                                                if (mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0] > 0)
                                                {
                                                    mEthashGlobalWorkSizeArray[0] += mEthashLocalWorkSizeArray[0] - mEthashGlobalWorkSizeArray[0] % mEthashLocalWorkSizeArray[0];
                                                }

                                                ComputeBuffer <byte> DAGCacheBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, cache.GetData().Length);

                                                fixed(byte *p = cache.GetData())
                                                Queue.Write <byte>(DAGCacheBuffer, true, 0, cache.GetData().Length, (IntPtr)p, null);

                                                ethashDAGBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadWrite, mEthashGlobalWorkSizeArray[0] * 8 * 64 /* ethashDAGSize */); // With this, we can remove a conditional statement in the DAG kernel.
                                                MemoryUsage    += DAGCacheBuffer.Size + ethashDAGBuffer.Size;

                                                DAGKernel.SetValueArgument <UInt32>(0, 0);
                                                DAGKernel.SetMemoryArgument(1, DAGCacheBuffer);
                                                DAGKernel.SetMemoryArgument(2, ethashDAGBuffer);
                                                DAGKernel.SetValueArgument <UInt32>(3, (UInt32)cache.GetData().Length / 64);
                                                DAGKernel.SetValueArgument <UInt32>(4, 0xffffffffu);

                                                for (long start = 0; start < ethashDAGSize / 64; start += mEthashGlobalWorkSizeArray[0])
                                                {
                                                    mEthashGlobalWorkOffsetArray[0] = start;
                                                    Queue.Execute(DAGKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null);
                                                    Queue.Finish();
                                                    if (Stopped || Stratum.GetJob() == null || !Stratum.GetJob().ID.Equals(ethashJobID))
                                                    {
                                                        break;
                                                    }
                                                }
                                                MemoryUsage -= DAGCacheBuffer.Size;
                                                DAGCacheBuffer.Dispose();
                                                if (Stopped || Stratum.GetJob() == null || !Stratum.GetJob().ID.Equals(ethashJobID))
                                                {
                                                    break;
                                                }
                                                sw.Stop();
                                                MainForm.Logger("Generated DAG for Epoch #" + ethashEpoch + " (" + (long)sw.Elapsed.TotalMilliseconds + "ms).");
                                            }

                                            consoleUpdateStopwatch.Start();

                                            while (!Stopped && Stratum.GetJob() != null && Stratum.GetJob().ID.Equals(ethashJobID) && Stratum.PoolExtranonce.Equals(ethashPoolExtranonce))
                                            {
                                                MarkAsAlive();

                                                // Get a new local extranonce if necessary.
                                                if ((ethashStartNonce & (0xfffffffffffffffful >> (ethashExtranonceByteArray.Length * 8 + 8)) + (ulong)mEthashGlobalWorkSizeArray[0]) >= ((ulong)0x1 << (64 - (ethashExtranonceByteArray.Length * 8 + 8))))
                                                {
                                                    break;
                                                }

                                                UInt64 target = (UInt64)((double)0xffff0000U / ethashDifficulty);
                                                searchKernel.SetMemoryArgument(0, ethashOutputBuffer);                    // g_output
                                                searchKernel.SetMemoryArgument(1, ethashHeaderBuffer);                    // g_header
                                                searchKernel.SetMemoryArgument(2, ethashDAGBuffer);                       // _g_dag
                                                searchKernel.SetValueArgument <UInt32>(3, (UInt32)(ethashDAGSize / 128)); // DAG_SIZE
                                                searchKernel.SetValueArgument <UInt64>(4, ethashStartNonce);              // start_nonce
                                                searchKernel.SetValueArgument <UInt64>(5, target);                        // target
                                                searchKernel.SetValueArgument <UInt32>(6, 0xffffffffu);                   // isolate

                                                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                                                sw.Start();
                                                ethashOutput[255] = 0; // ethashOutput[255] is used as an atomic counter.
                                                Queue.Write <UInt32>(ethashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null);
                                                mEthashGlobalWorkOffsetArray[0] = 0;
                                                Queue.Execute(searchKernel, mEthashGlobalWorkOffsetArray, mEthashGlobalWorkSizeArray, mEthashLocalWorkSizeArray, null);
                                                Queue.Read <UInt32>(ethashOutputBuffer, true, 0, 256, (IntPtr)ethashOutputPtr, null);
                                                if (Stratum.GetJob() != null && Stratum.GetJob().ID.Equals(ethashJobID))
                                                {
                                                    for (int i = 0; i < ethashOutput[255]; ++i)
                                                    {
                                                        Stratum.Submit(Device, ethashWork.GetJob(), ethashStartNonce + (UInt64)ethashOutput[i]);
                                                    }
                                                }
                                                ethashStartNonce += (UInt64)mEthashGlobalWorkSizeArray[0];

                                                sw.Stop();
                                                Speed = ((double)mEthashGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds;
                                                Device.TotalHashesPrimaryAlgorithm += (double)mEthashGlobalWorkSizeArray[0];
                                                if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                                                {
                                                    MainForm.Logger("Device #" + DeviceIndex + " (Ethash): " + String.Format("{0:N2} Mh/s", Speed / (1000000)));
                                                    consoleUpdateStopwatch.Restart();
                                                }
                                            }
                                        }
                                    } catch (Exception ex) {
                                        MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                                        Speed = 0;
                                        if (UnrecoverableException.IsUnrecoverableException(ex))
                                        {
                                            this.UnrecoverableException = new UnrecoverableException(ex, Device);
                                            Stop();
                                        }
                                        else
                                        {
                                            MainForm.Logger("Restarting miner thread...");
                                            System.Threading.Thread.Sleep(Parameters.WaitTimeForRestartingMinerThreadInMilliseconds);
                                        }
                                    } finally {
                                        if (ethashDAGBuffer != null)
                                        {
                                            MemoryUsage -= ethashDAGBuffer.Size;
                                            ethashDAGBuffer.Dispose();
                                            ethashDAGBuffer = null;
                                        }
                                    }
                                }
            } catch (UnrecoverableException ex) {
                this.UnrecoverableException = ex;
            } catch (Exception ex) {
                this.UnrecoverableException = new UnrecoverableException(ex, Device);
            } finally {
                MarkAsDone();
                MemoryUsage = 0;
                if (program != null)
                {
                    program.Dispose();
                }
                program = null;
            }
        }
Esempio n. 8
0
        override unsafe protected void MinerThread()
        {
            Random        r             = new Random();
            ComputeDevice computeDevice = OpenCLDevice.GetComputeDevice();

            MarkAsAlive();

            MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");
            MainForm.Logger("NiceHash mode is " + (NiceHashMode ? "on" : "off") + ".");

            ComputeProgram program;

            try { mProgramArrayMutex.WaitOne(5000); } catch (Exception) { }
            if (mProgramArray.ContainsKey(new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])))
            {
                program       = mProgramArray[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
                searchKernel0 = mSearchKernel0Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
                searchKernel1 = mSearchKernel1Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
                searchKernel2 = mSearchKernel2Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
                searchKernel3 = mSearchKernel3Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])];
            }
            else
            {
                try
                {
                    if (localWorkSizeA[0] != 8)
                    {
                        throw new Exception("No suitable binary file was found.");
                    }
                    string fileName = @"BinaryKernels\" + computeDevice.Name + "_cryptonight.bin";
                    byte[] binary   = System.IO.File.ReadAllBytes(fileName);
                    program = new ComputeProgram(Context, new List <byte[]>()
                    {
                        binary
                    }, new List <ComputeDevice>()
                    {
                        computeDevice
                    });
                    MainForm.Logger("Loaded " + fileName + " for Device #" + DeviceIndex + ".");
                }
                catch (Exception)
                {
                    String source = System.IO.File.ReadAllText(@"Kernels\cryptonight.cl");
                    program = new ComputeProgram(Context, source);
                    MainForm.Logger(@"Loaded Kernels\cryptonight.cl for Device #" + DeviceIndex + ".");
                }
                String buildOptions = (OpenCLDevice.GetVendor() == "AMD"    ? "-O5" : //"-O1 " :
                                       OpenCLDevice.GetVendor() == "NVIDIA" ? "" :    //"-cl-nv-opt-level=1 -cl-nv-maxrregcount=256 " :
                                       "")
                                      + " -IKernels -DWORKSIZE=" + localWorkSizeA[0];
                try
                {
                    program.Build(OpenCLDevice.DeviceList, buildOptions, null, IntPtr.Zero);
                }
                catch (Exception)
                {
                    MainForm.Logger(program.GetBuildLog(computeDevice));
                    throw;
                }
                MainForm.Logger("Built CryptoNight program for Device #" + DeviceIndex + ".");
                MainForm.Logger("Build options: " + buildOptions);
                mProgramArray[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])]       = program;
                mSearchKernel0Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])] = searchKernel0 = program.CreateKernel("search");
                mSearchKernel1Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])] = searchKernel1 = program.CreateKernel("search1");
                mSearchKernel2Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])] = searchKernel2 = program.CreateKernel("search2");
                mSearchKernel3Array[new ProgramArrayIndex(DeviceIndex, localWorkSizeA[0])] = searchKernel3 = program.CreateKernel("search3");
            }
            try { mProgramArrayMutex.ReleaseMutex(); } catch (Exception) { }

            fixed(long *globalWorkOffsetAPtr = globalWorkOffsetA)
            fixed(long *globalWorkOffsetBPtr = globalWorkOffsetB)
            fixed(long *globalWorkSizeAPtr   = globalWorkSizeA)
            fixed(long *globalWorkSizeBPtr   = globalWorkSizeB)
            fixed(long *localWorkSizeAPtr    = localWorkSizeA)
            fixed(long *localWorkSizeBPtr    = localWorkSizeB)
            fixed(Int32 * terminatePtr       = terminate)
            fixed(byte *inputPtr             = input)
            fixed(UInt32 * outputPtr         = output)
            {
                while (!Stopped)
                {
                    MarkAsAlive();

                    try {
                        searchKernel0.SetMemoryArgument(0, inputBuffer);
                        searchKernel0.SetMemoryArgument(1, scratchpadsBuffer);
                        searchKernel0.SetMemoryArgument(2, statesBuffer);

                        searchKernel1.SetMemoryArgument(0, scratchpadsBuffer);
                        searchKernel1.SetMemoryArgument(1, statesBuffer);
                        searchKernel1.SetMemoryArgument(2, terminateBuffer);

                        searchKernel2.SetMemoryArgument(0, scratchpadsBuffer);
                        searchKernel2.SetMemoryArgument(1, statesBuffer);

                        searchKernel3.SetMemoryArgument(0, statesBuffer);
                        searchKernel3.SetMemoryArgument(1, outputBuffer);

                        // Wait for the first job to arrive.
                        int elapsedTime = 0;
                        while ((mStratum == null || mStratum.GetJob() == null) && elapsedTime < 60000)
                        {
                            Thread.Sleep(100);
                            elapsedTime += 100;
                        }
                        if (mStratum == null || mStratum.GetJob() == null)
                        {
                            throw new TimeoutException("Stratum server failed to send a new job.");
                        }

                        System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                        CryptoNightStratum.Work      work;

                        while (!Stopped && (work = mStratum.GetWork()) != null)
                        {
                            MarkAsAlive();

                            var job = work.GetJob();
                            Array.Copy(Utilities.StringToByteArray(job.Blob), input, 76);
                            byte   localExtranonce = (byte)work.LocalExtranonce;
                            byte[] targetByteArray = Utilities.StringToByteArray(job.Target);
                            UInt32 startNonce;
                            if (NiceHashMode)
                            {
                                startNonce = ((UInt32)input[42] << (8 * 3)) | ((UInt32)localExtranonce << (8 * 2)) | (UInt32)(r.Next(0, int.MaxValue) & (0x0000ffffu));
                            }
                            else
                            {
                                startNonce = ((UInt32)localExtranonce << (8 * 3)) | (UInt32)(r.Next(0, int.MaxValue) & (0x00ffffffu));
                            }
                            UInt32 target = ((UInt32)targetByteArray[0] << 0)
                                            | ((UInt32)targetByteArray[1] << 8)
                                            | ((UInt32)targetByteArray[2] << 16)
                                            | ((UInt32)targetByteArray[3] << 24);
                            searchKernel3.SetValueArgument <UInt32>(2, target);

                            Queue.Write <byte>(inputBuffer, true, 0, 76, (IntPtr)inputPtr, null);

                            consoleUpdateStopwatch.Start();

                            while (!Stopped && mStratum.GetJob().Equals(job))
                            {
                                MarkAsAlive();

                                globalWorkOffsetA[0] = globalWorkOffsetB[0] = startNonce;

                                // Get a new local extranonce if necessary.
                                if (NiceHashMode)
                                {
                                    if ((startNonce & 0xffff) + (UInt32)globalWorkSizeA[0] >= 0x10000)
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    if ((startNonce & 0xffffff) + (UInt32)globalWorkSizeA[0] >= 0x1000000)
                                    {
                                        break;
                                    }
                                }

                                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                                sw.Start();
                                output[255] = 0; // output[255] is used as an atomic counter.
                                Queue.Write <UInt32>(outputBuffer, true, 0, outputSize, (IntPtr)outputPtr, null);
                                terminate[0] = 0;
                                Queue.Write <Int32>(terminateBuffer, true, 0, 1, (IntPtr)terminatePtr, null);
                                Queue.Execute(searchKernel0, globalWorkOffsetA, globalWorkSizeA, localWorkSizeA, null);
                                Queue.Finish();
                                if (Stopped)
                                {
                                    break;
                                }
                                Queue.Execute(searchKernel1, globalWorkOffsetB, globalWorkSizeB, localWorkSizeB, null);
                                Queue.Finish();
                                if (Stopped)
                                {
                                    break;
                                }
                                Queue.Execute(searchKernel2, globalWorkOffsetA, globalWorkSizeA, localWorkSizeA, null);
                                Queue.Finish();
                                if (Stopped)
                                {
                                    break;
                                }
                                Queue.Execute(searchKernel3, globalWorkOffsetB, globalWorkSizeB, localWorkSizeB, null);
                                Queue.Finish(); // Run the above statement before leaving the current local scope.
                                if (Stopped)
                                {
                                    break;
                                }

                                Queue.Read <UInt32>(outputBuffer, true, 0, outputSize, (IntPtr)outputPtr, null);
                                if (mStratum.GetJob().Equals(job))
                                {
                                    for (int i = 0; i < output[255]; ++i)
                                    {
                                        String result = "";
                                        for (int j = 0; j < 8; ++j)
                                        {
                                            UInt32 word = output[256 + i * 8 + j];
                                            result += String.Format("{0:x2}{1:x2}{2:x2}{3:x2}", ((word >> 0) & 0xff), ((word >> 8) & 0xff), ((word >> 16) & 0xff), ((word >> 24) & 0xff));
                                        }
                                        mStratum.Submit(GatelessGateDevice, job, output[i], result);
                                    }
                                }
                                startNonce += (UInt32)globalWorkSizeA[0];

                                sw.Stop();
                                Speed = ((double)globalWorkSizeA[0]) / sw.Elapsed.TotalSeconds;
                                if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                                {
                                    MainForm.Logger("Device #" + DeviceIndex + " (CryptoNight): " + String.Format("{0:N2} h/s", Speed));
                                    consoleUpdateStopwatch.Restart();
                                }
                            }
                        }
                    } catch (Exception ex) {
                        MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                        if (UnrecoverableException.IsUnrecoverableException(ex))
                        {
                            this.UnrecoverableException = new UnrecoverableException(ex, GatelessGateDevice);
                            Stop();
                        }
                    }

                    Speed = 0;

                    if (!Stopped)
                    {
                        MainForm.Logger("Restarting miner thread...");
                        System.Threading.Thread.Sleep(5000);
                    }
                }
            }

            MarkAsDone();
        }
Esempio n. 9
0
        override unsafe protected void MinerThread()
        {
            ComputeProgram program = null;

            try {
                Random r = new Random();

                MarkAsAlive();

                MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");

                program = BuildProgram("pascal", mPascalLocalWorkSizeArray[0], "-O1", "", "");

                using (var pascalSearchKernel = program.CreateKernel("search"))
                    using (var pascalInputBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, sPascalInputSize))
                        using (var pascalOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, sPascalOutputSize))
                            using (var pascalMidstateBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, sPascalMidstateSize))
                                fixed(long *pascalGlobalWorkOffsetArrayPtr = mPascalGlobalWorkOffsetArray)
                                fixed(long *pascalGlobalWorkSizeArrayPtr = mPascalGlobalWorkSizeArray)
                                fixed(long *pascalLocalWorkSizeArrayPtr  = mPascalLocalWorkSizeArray)
                                fixed(byte *pascalMidstatePtr            = mPascalMidstate)
                                fixed(byte *pascalInputPtr     = mPascalInput)
                                fixed(UInt32 * pascalOutputPtr = mPascalOutput)
                                while (!Stopped)
                                {
                                    MarkAsAlive();

                                    try
                                    {
                                        pascalSearchKernel.SetMemoryArgument(0, pascalInputBuffer);
                                        pascalSearchKernel.SetMemoryArgument(1, pascalOutputBuffer);
                                        pascalSearchKernel.SetMemoryArgument(4, pascalMidstateBuffer);

                                        // Wait for the first PascalJob to arrive.
                                        int elapsedTime = 0;
                                        while ((Stratum == null || Stratum.GetJob() == null) && elapsedTime < Parameters.TimeoutForFirstJobInMilliseconds && !Stopped)
                                        {
                                            Thread.Sleep(100);
                                            elapsedTime += 100;
                                        }
                                        if (Stratum == null || Stratum.GetJob() == null)
                                        {
                                            throw new TimeoutException("Stratum server failed to send a new PascalJob.");
                                        }

                                        System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                                        PascalStratum.Work           pascalWork;
                                        PascalStratum.Job            pascalJob;

                                        while (!Stopped && (pascalWork = Stratum.GetWork()) != null && (pascalJob = pascalWork.Job) != null)
                                        {
                                            MarkAsAlive();

                                            Array.Copy(pascalWork.Blob, mPascalInput, sPascalInputSize);
                                            CalculatePascalMidState();
                                            Queue.Write <byte>(pascalMidstateBuffer, true, 0, sPascalMidstateSize, (IntPtr)pascalMidstatePtr, null);
                                            UInt32 pascalStartNonce = (UInt32)(r.Next(0, int.MaxValue));
                                            UInt64 PascalTarget     = (UInt64)((double)0xffff0000UL / Stratum.Difficulty);
                                            pascalSearchKernel.SetValueArgument <UInt64>(3, PascalTarget);
                                            Queue.Write <byte>(pascalInputBuffer, true, 0, sPascalInputSize, (IntPtr)pascalInputPtr, null);

                                            consoleUpdateStopwatch.Start();

                                            while (!Stopped && Stratum.GetJob() != null && Stratum.GetJob().Equals(pascalJob))
                                            {
                                                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                                                sw.Start();

                                                MarkAsAlive();

                                                pascalSearchKernel.SetValueArgument <UInt32>(2, pascalStartNonce);

                                                // Get a new local extranonce if necessary.
                                                if (0xffffffffu - pascalStartNonce < (UInt32)mPascalGlobalWorkSizeArray[0])
                                                {
                                                    break;
                                                }

                                                mPascalOutput[255] = 0; // mPascalOutput[255] is used as an atomic counter.
                                                Queue.Write <UInt32>(pascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null);
                                                Queue.Execute(pascalSearchKernel, mPascalGlobalWorkOffsetArray, mPascalGlobalWorkSizeArray, mPascalLocalWorkSizeArray, null);
                                                Queue.Read <UInt32>(pascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null);
                                                if (Stratum.GetJob() != null && Stratum.GetJob().Equals(pascalJob))
                                                {
                                                    for (int i = 0; i < mPascalOutput[255]; ++i)
                                                    {
                                                        Stratum.Submit(Device, pascalWork, mPascalOutput[i]);
                                                    }
                                                }
                                                pascalStartNonce += (UInt32)mPascalGlobalWorkSizeArray[0];

                                                sw.Stop();
                                                Speed = ((double)mPascalGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds;
                                                Device.TotalHashesPrimaryAlgorithm += (double)mPascalGlobalWorkSizeArray[0];
                                                if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                                                {
                                                    MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Pascal)", Speed / 1000000));
                                                    consoleUpdateStopwatch.Restart();
                                                }
                                            }
                                        }
                                    } catch (Exception ex) {
                                        MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                                        if (UnrecoverableException.IsUnrecoverableException(ex))
                                        {
                                            this.UnrecoverableException = new UnrecoverableException(ex, Device);
                                            Stop();
                                        }
                                    }

                                    Speed = 0;

                                    if (!Stopped)
                                    {
                                        MainForm.Logger("Restarting miner thread...");
                                        System.Threading.Thread.Sleep(Parameters.WaitTimeForRestartingMinerThreadInMilliseconds);
                                    }
                                }
                MarkAsDone();

                program.Dispose();
            } catch (UnrecoverableException ex) {
                if (program != null)
                {
                    program.Dispose();
                }
                this.UnrecoverableException = ex;
            } catch (Exception ex) {
                if (program != null)
                {
                    program.Dispose();
                }
                this.UnrecoverableException = new UnrecoverableException(ex, Device);
            }
        }
Esempio n. 10
0
        private void StreamReaderThread()
        {
            Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
            int errorCount = 0;

            UnrecoverableException = null;

            do
            {
                try {
                    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                    sw.Start();

                    try { mMutex.WaitOne(5000); } catch (Exception) { }

                    mClient       = new TcpClient(ServerAddress, ServerPort);
                    mStream       = mClient.GetStream();
                    mStreamReader = new StreamReader(mStream, System.Text.Encoding.ASCII, false, 65536);
                    mStreamWriter = new StreamWriter(mStream, System.Text.Encoding.ASCII, 65536);
                    mStreamReader.BaseStream.ReadTimeout  = 3 * 60 * 1000;
                    mStreamWriter.BaseStream.WriteTimeout = 10 * 1000;
                    mReconnectionRequested = false;

                    try { mMutex.ReleaseMutex(); } catch (Exception) { }

                    Authorize();

                    while (!Stopped && !mReconnectionRequested)
                    {
                        string line;
                        try {
                            line = mStreamReader.ReadLine();
                        } catch (Exception) {
                            throw new StratumServerUnavailableException();
                        }
                        if (line == null)
                        {
                            throw new StratumServerUnavailableException();
                        }

                        if (Stopped)
                        {
                            break;
                        }
                        if (line != "")
                        {
                            ProcessLine(line);
                        }
                        if (sw.ElapsedMilliseconds >= 60 * 60 * 1000)
                        {
                            mReconnectionRequested = true;
                        }
                    }
                } catch (UnrecoverableException ex) {
                    this.UnrecoverableException = ex;
                } catch (Exception ex) {
                    MainForm.Logger("Exception in Stratum.StreamReaderThread(): " + ex.ToString());
                    if (UnrecoverableException.IsUnrecoverableException(ex))
                    {
                        this.UnrecoverableException = new UnrecoverableException(ex.Message);
                    }
                    else if (++errorCount < 4)
                    {
                        MainForm.Logger("Reconnecting to the server...");
                        System.Threading.Thread.Sleep(5000);
                    }
                    else
                    {
                        this.UnrecoverableException = new StratumServerUnavailableException();
                    }
                }

                try {
                    mClient.Close();
                    mClient = null;
                } catch (Exception) { }
            } while (!Stopped && UnrecoverableException == null);
        }
Esempio n. 11
0
        override unsafe protected void MinerThread()
        {
            ComputeProgram program = null;

            try {
                Random r = new Random();

                MarkAsAlive();

                MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");

                program = BuildProgram(
                    "lbry",
                    mLbryLocalWorkSizeArray[0],
                    "-O1 -DITERATIONS=" + mIterations,
                    "-DITERATIONS=" + mIterations,
                    "-DITERATIONS=" + mIterations);

                using (var lbrySearchKernel = program.CreateKernel("search_combined"))
                    using (var lbryInputBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, 112))
                        using (var lbryOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, lbryOutputSize))
                            fixed(long *lbryGlobalWorkOffsetArrayPtr = mLbryGlobalWorkOffsetArray)
                            fixed(long *lbryGlobalWorkSizeArrayPtr = mLbryGlobalWorkSizeArray)
                            fixed(long *lbryLocalWorkSizeArrayPtr  = mLbryLocalWorkSizeArray)
                            fixed(byte *lbryInputPtr     = mLbryInput)
                            fixed(UInt32 * lbryOutputPtr = mLbryOutput)
                            while (!Stopped)
                            {
                                MarkAsAlive();

                                try
                                {
                                    lbrySearchKernel.SetMemoryArgument(0, lbryInputBuffer);
                                    lbrySearchKernel.SetMemoryArgument(1, lbryOutputBuffer);

                                    // Wait for the first lbryJob to arrive.
                                    int elapsedTime = 0;
                                    while ((Stratum == null || Stratum.GetJob() == null) && elapsedTime < Parameters.TimeoutForFirstJobInMilliseconds && !Stopped)
                                    {
                                        Thread.Sleep(100);
                                        elapsedTime += 100;
                                    }
                                    if (Stratum == null || Stratum.GetJob() == null)
                                    {
                                        throw new TimeoutException("Stratum server failed to send a new lbryJob.");
                                    }

                                    System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                                    LbryStratum.Work             lbryWork;
                                    LbryStratum.Job lbryJob;

                                    while (!Stopped && (lbryWork = Stratum.GetWork()) != null && (lbryJob = lbryWork.Job) != null)
                                    {
                                        MarkAsAlive();

                                        Array.Copy(lbryWork.Blob, mLbryInput, 112);
                                        UInt32 lbryStartNonce = (UInt32)(r.Next(0, int.MaxValue));
                                        UInt64 lbryTarget     = (UInt64)((double)0xffff0000UL / (Stratum.Difficulty / 256));
                                        lbrySearchKernel.SetValueArgument <UInt64>(3, lbryTarget);
                                        Queue.Write <byte>(lbryInputBuffer, true, 0, 112, (IntPtr)lbryInputPtr, null);

                                        consoleUpdateStopwatch.Start();

                                        while (!Stopped && Stratum.GetJob() != null && Stratum.GetJob().Equals(lbryJob))
                                        {
                                            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                                            sw.Start();

                                            MarkAsAlive();

                                            lbrySearchKernel.SetValueArgument <UInt32>(2, lbryStartNonce);

                                            // Get a new local extranonce if necessary.
                                            if (0xffffffffu - lbryStartNonce < (UInt32)mLbryGlobalWorkSizeArray[0] * mIterations)
                                            {
                                                break;
                                            }

                                            mLbryOutput[255] = 0; // mLbryOutput[255] is used as an atomic counter.
                                            Queue.Write <UInt32>(lbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null);
                                            Queue.Execute(lbrySearchKernel, mLbryGlobalWorkOffsetArray, mLbryGlobalWorkSizeArray, mLbryLocalWorkSizeArray, null);
                                            Queue.Read <UInt32>(lbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null);
                                            if (Stratum.GetJob() != null && Stratum.GetJob().Equals(lbryJob))
                                            {
                                                for (int i = 0; i < mLbryOutput[255]; ++i)
                                                {
                                                    String result = "";
                                                    for (int j = 0; j < 8; ++j)
                                                    {
                                                        UInt32 word = mLbryOutput[256 + i * 8 + j];
                                                        result += String.Format("{0:x2}{1:x2}{2:x2}{3:x2}", ((word >> 0) & 0xff), ((word >> 8) & 0xff), ((word >> 16) & 0xff), ((word >> 24) & 0xff));
                                                    }
                                                    Stratum.Submit(Device, lbryWork, mLbryOutput[i], result);
                                                }
                                            }
                                            lbryStartNonce += (UInt32)mLbryGlobalWorkSizeArray[0] * (uint)mIterations;

                                            sw.Stop();
                                            Speed = ((double)mLbryGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds * mIterations;
                                            Device.TotalHashesPrimaryAlgorithm += (double)mLbryGlobalWorkSizeArray[0] * mIterations;
                                            if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                                            {
                                                MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Lbry)", Speed / 1000000));
                                                consoleUpdateStopwatch.Restart();
                                            }
                                        }
                                    }
                                } catch (Exception ex) {
                                    MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                                    if (UnrecoverableException.IsUnrecoverableException(ex))
                                    {
                                        this.UnrecoverableException = new UnrecoverableException(ex, Device);
                                        Stop();
                                    }
                                }

                                Speed = 0;

                                if (!Stopped)
                                {
                                    MainForm.Logger("Restarting miner thread...");
                                    System.Threading.Thread.Sleep(Parameters.WaitTimeForRestartingMinerThreadInMilliseconds);
                                }
                            }
            } catch (UnrecoverableException ex) {
                this.UnrecoverableException = ex;
            } catch (Exception ex) {
                this.UnrecoverableException = new UnrecoverableException(ex, Device);
            } finally {
                MarkAsDone();
                MemoryUsage = 0;
                if (program != null)
                {
                    program.Dispose(); program = null;
                }
            }
        }
Esempio n. 12
0
        override unsafe protected void MinerThread()
        {
            Random r = new Random();

            MarkAsAlive();

            MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");

            BuildPascalProgram();

            fixed(long *pascalGlobalWorkOffsetArrayPtr = mPascalGlobalWorkOffsetArray)
            fixed(long *pascalGlobalWorkSizeArrayPtr = mPascalGlobalWorkSizeArray)
            fixed(long *pascalLocalWorkSizeArrayPtr  = mPascalLocalWorkSizeArray)
            fixed(byte *pascalMidstatePtr            = mPascalMidstate)
            fixed(byte *pascalInputPtr     = mPascalInput)
            fixed(UInt32 * pascalOutputPtr = mPascalOutput)
            while (!Stopped)
            {
                MarkAsAlive();

                try
                {
                    mPascalSearchKernel.SetMemoryArgument(0, mPascalInputBuffer);
                    mPascalSearchKernel.SetMemoryArgument(1, mPascalOutputBuffer);
                    mPascalSearchKernel.SetMemoryArgument(4, mPascalMidstateBuffer);

                    // Wait for the first PascalJob to arrive.
                    int elapsedTime = 0;
                    while ((mPascalStratum == null || mPascalStratum.GetJob() == null) && elapsedTime < 60000)
                    {
                        Thread.Sleep(100);
                        elapsedTime += 100;
                    }
                    if (mPascalStratum == null || mPascalStratum.GetJob() == null)
                    {
                        throw new TimeoutException("Stratum server failed to send a new PascalJob.");
                    }

                    System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                    PascalStratum.Work           pascalWork;

                    while (!Stopped && (pascalWork = mPascalStratum.GetWork()) != null)
                    {
                        MarkAsAlive();

                        var pascalJob = pascalWork.Job;
                        Array.Copy(pascalWork.Blob, mPascalInput, sPascalInputSize);
                        CalculatePascalMidState();
                        Queue.Write <byte>(mPascalMidstateBuffer, true, 0, sPascalMidstateSize, (IntPtr)pascalMidstatePtr, null);
                        UInt32 pascalStartNonce = (UInt32)(r.Next(0, int.MaxValue));
                        UInt64 PascalTarget     = (UInt64)((double)0xffff0000UL / mPascalStratum.Difficulty);
                        mPascalSearchKernel.SetValueArgument <UInt64>(3, PascalTarget);
                        Queue.Write <byte>(mPascalInputBuffer, true, 0, sPascalInputSize, (IntPtr)pascalInputPtr, null);

                        consoleUpdateStopwatch.Start();

                        while (!Stopped && mPascalStratum.GetJob().Equals(pascalJob))
                        {
                            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                            sw.Start();

                            MarkAsAlive();

                            mPascalSearchKernel.SetValueArgument <UInt32>(2, pascalStartNonce);

                            // Get a new local extranonce if necessary.
                            if (0xffffffffu - pascalStartNonce < (UInt32)mPascalGlobalWorkSizeArray[0])
                            {
                                break;
                            }

                            mPascalOutput[255] = 0; // mPascalOutput[255] is used as an atomic counter.
                            Queue.Write <UInt32>(mPascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null);
                            Queue.Execute(mPascalSearchKernel, mPascalGlobalWorkOffsetArray, mPascalGlobalWorkSizeArray, mPascalLocalWorkSizeArray, null);
                            Queue.Read <UInt32>(mPascalOutputBuffer, true, 0, sPascalOutputSize, (IntPtr)pascalOutputPtr, null);
                            if (mPascalStratum.GetJob().Equals(pascalJob))
                            {
                                for (int i = 0; i < mPascalOutput[255]; ++i)
                                {
                                    mPascalStratum.Submit(GatelessGateDevice, pascalWork, mPascalOutput[i]);
                                }
                            }
                            pascalStartNonce += (UInt32)mPascalGlobalWorkSizeArray[0];

                            sw.Stop();
                            Speed = ((double)mPascalGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds;
                            if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                            {
                                MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Pascal)", Speed / 1000000));
                                consoleUpdateStopwatch.Restart();
                            }
                        }
                    }
                } catch (Exception ex) {
                    MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                    if (UnrecoverableException.IsUnrecoverableException(ex))
                    {
                        this.UnrecoverableException = new UnrecoverableException(ex, GatelessGateDevice);
                        Stop();
                    }
                }

                Speed = 0;

                if (!Stopped)
                {
                    MainForm.Logger("Restarting miner thread...");
                    System.Threading.Thread.Sleep(5000);
                }
            }

            MarkAsDone();
        }
        override unsafe protected void MinerThread()
        {
            Random r = new Random();

            MarkAsAlive();

            MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");

            BuildNeoScryptProgram();

            fixed(long *neoscryptGlobalWorkOffsetArrayPtr = mNeoScryptGlobalWorkOffsetArray)
            fixed(long *neoscryptGlobalWorkSizeArrayPtr = mNeoScryptGlobalWorkSizeArray)
            fixed(long *neoscryptLocalWorkSizeArrayPtr  = mNeoScryptLocalWorkSizeArray)
            fixed(byte *neoscryptInputPtr     = mNeoScryptInput)
            fixed(UInt32 * neoscryptOutputPtr = mNeoScryptOutput)
            using (ComputeBuffer <byte> mNeoScryptGlobalCacheBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadWrite, (mNeoScryptGlobalWorkSizeArray[0] * 32768)))
                while (!Stopped)
                {
                    MarkAsAlive();

                    try {
                        mNeoScryptSearchKernel.SetMemoryArgument(0, mNeoScryptInputBuffer);
                        mNeoScryptSearchKernel.SetMemoryArgument(1, mNeoScryptOutputBuffer);
                        mNeoScryptSearchKernel.SetMemoryArgument(2, mNeoScryptGlobalCacheBuffer);

                        // Wait for the first NeoScryptJob to arrive.
                        int elapsedTime = 0;
                        while ((mNeoScryptStratum == null || mNeoScryptStratum.GetJob() == null) && elapsedTime < 60000)
                        {
                            Thread.Sleep(100);
                            elapsedTime += 100;
                        }
                        if (mNeoScryptStratum == null || mNeoScryptStratum.GetJob() == null)
                        {
                            throw new TimeoutException("Stratum server failed to send a new job.");
                        }

                        System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                        NeoScryptStratum.Work        neoscryptWork;

                        while (!Stopped && (neoscryptWork = mNeoScryptStratum.GetWork()) != null)
                        {
                            MarkAsAlive();

                            var neoscryptJob = neoscryptWork.Job;
                            Array.Copy(neoscryptWork.Blob, mNeoScryptInput, sNeoScryptInputSize);
                            UInt32 neoscryptStartNonce = (UInt32)(r.Next(0, int.MaxValue));
                            Queue.Write <byte>(mNeoScryptInputBuffer, true, 0, sNeoScryptInputSize, (IntPtr)neoscryptInputPtr, null);

                            consoleUpdateStopwatch.Start();

                            while (!Stopped && mNeoScryptStratum.GetJob().Equals(neoscryptJob))
                            {
                                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                                sw.Start();

                                MarkAsAlive();

                                UInt32 NeoScryptTarget = (UInt32)((double)0xffff0000U / (mNeoScryptStratum.Difficulty * 65536));
                                mNeoScryptSearchKernel.SetValueArgument <UInt32>(3, NeoScryptTarget);
                                mNeoScryptGlobalWorkOffsetArray[0] = neoscryptStartNonce;

                                // Get a new local extranonce if necessary.
                                if (0xffffffffu - neoscryptStartNonce < (UInt32)mNeoScryptGlobalWorkSizeArray[0])
                                {
                                    break;
                                }

                                mNeoScryptOutput[255] = 0; // mNeoScryptOutput[255] is used as an atomic counter.
                                Queue.Write <UInt32>(mNeoScryptOutputBuffer, true, 0, sNeoScryptOutputSize, (IntPtr)neoscryptOutputPtr, null);
                                Queue.Execute(mNeoScryptSearchKernel, mNeoScryptGlobalWorkOffsetArray, mNeoScryptGlobalWorkSizeArray, mNeoScryptLocalWorkSizeArray, null);
                                Queue.Read <UInt32>(mNeoScryptOutputBuffer, true, 0, sNeoScryptOutputSize, (IntPtr)neoscryptOutputPtr, null);
                                if (mNeoScryptStratum.GetJob().Equals(neoscryptJob))
                                {
                                    for (int i = 0; i < mNeoScryptOutput[255]; ++i)
                                    {
                                        mNeoScryptStratum.Submit(GatelessGateDevice, neoscryptWork, mNeoScryptOutput[i]);
                                    }
                                }
                                neoscryptStartNonce += (UInt32)mNeoScryptGlobalWorkSizeArray[0];

                                sw.Stop();
                                Speed = ((double)mNeoScryptGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds;
                                if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                                {
                                    MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Kh/s (NeoScrypt)", Speed / 1000));
                                    consoleUpdateStopwatch.Restart();
                                }
                            }
                        }
                    } catch (Exception ex) {
                        MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                        if (UnrecoverableException.IsUnrecoverableException(ex))
                        {
                            this.UnrecoverableException = new UnrecoverableException(ex, GatelessGateDevice);
                            Stop();
                        }
                    }

                    Speed = 0;

                    if (!Stopped)
                    {
                        MainForm.Logger("Restarting miner thread...");
                        System.Threading.Thread.Sleep(5000);
                    }
                }
            MarkAsDone();
        }
Esempio n. 14
0
        override unsafe protected void MinerThread()
        {
            ComputeProgram       program = null;
            ComputeBuffer <byte> neoScryptGlobalCacheBuffer = null;

            try {
                Random r = new Random();

                MarkAsAlive();

                MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");

                program = BuildProgram("neoscrypt", mNeoScryptLocalWorkSizeArray[0], "-O5 -legacy", "", "");

                neoScryptGlobalCacheBuffer = OpenCLDevice.RequestComputeByteBuffer(ComputeMemoryFlags.ReadWrite, (mNeoScryptGlobalWorkSizeArray[0] * 32768));
                MemoryUsage = sNeoScryptInputSize + sNeoScryptOutputSize + neoScryptGlobalCacheBuffer.Size;

                using (var neoScryptSearchKernel = program.CreateKernel("search"))
                    using (var neoScryptInputBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, sNeoScryptInputSize))
                        using (var neoScryptOutputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, sNeoScryptOutputSize))
                            fixed(long *neoscryptGlobalWorkOffsetArrayPtr = mNeoScryptGlobalWorkOffsetArray)
                            fixed(long *neoscryptGlobalWorkSizeArrayPtr = mNeoScryptGlobalWorkSizeArray)
                            fixed(long *neoscryptLocalWorkSizeArrayPtr  = mNeoScryptLocalWorkSizeArray)
                            fixed(byte *neoscryptInputPtr     = mNeoScryptInput)
                            fixed(UInt32 * neoscryptOutputPtr = mNeoScryptOutput)
                            while (!Stopped)
                            {
                                MarkAsAlive();

                                try {
                                    neoScryptSearchKernel.SetMemoryArgument(0, neoScryptInputBuffer);
                                    neoScryptSearchKernel.SetMemoryArgument(1, neoScryptOutputBuffer);
                                    neoScryptSearchKernel.SetMemoryArgument(2, neoScryptGlobalCacheBuffer);

                                    // Wait for the first NeoScryptJob to arrive.
                                    int elapsedTime = 0;
                                    while ((Stratum == null || Stratum.GetJob() == null) && elapsedTime < Parameters.TimeoutForFirstJobInMilliseconds && !Stopped)
                                    {
                                        Thread.Sleep(100);
                                        elapsedTime += 100;
                                    }
                                    if (Stratum == null || Stratum.GetJob() == null)
                                    {
                                        throw new TimeoutException("Stratum server failed to send a new job.");
                                    }

                                    System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                                    NeoScryptStratum.Work        neoscryptWork;
                                    NeoScryptStratum.Job         neoscryptJob;

                                    while (!Stopped && (neoscryptWork = Stratum.GetWork()) != null && (neoscryptJob = neoscryptWork.Job) != null)
                                    {
                                        MarkAsAlive();

                                        Array.Copy(neoscryptWork.Blob, mNeoScryptInput, sNeoScryptInputSize);
                                        UInt32 neoscryptStartNonce = (UInt32)(r.Next(0, int.MaxValue));
                                        Queue.Write <byte>(neoScryptInputBuffer, true, 0, sNeoScryptInputSize, (IntPtr)neoscryptInputPtr, null);

                                        consoleUpdateStopwatch.Start();

                                        while (!Stopped && Stratum.GetJob() != null && Stratum.GetJob().Equals(neoscryptJob))
                                        {
                                            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                                            sw.Start();

                                            MarkAsAlive();

                                            UInt32 NeoScryptTarget = (UInt32)((double)0xffff0000U / (Stratum.Difficulty * 65536));
                                            neoScryptSearchKernel.SetValueArgument <UInt32>(3, NeoScryptTarget);
                                            mNeoScryptGlobalWorkOffsetArray[0] = neoscryptStartNonce;

                                            // Get a new local extranonce if necessary.
                                            if (0xffffffffu - neoscryptStartNonce < (UInt32)mNeoScryptGlobalWorkSizeArray[0])
                                            {
                                                break;
                                            }

                                            mNeoScryptOutput[255] = 0; // mNeoScryptOutput[255] is used as an atomic counter.
                                            Queue.Write <UInt32>(neoScryptOutputBuffer, true, 0, sNeoScryptOutputSize, (IntPtr)neoscryptOutputPtr, null);
                                            Queue.Execute(neoScryptSearchKernel, mNeoScryptGlobalWorkOffsetArray, mNeoScryptGlobalWorkSizeArray, mNeoScryptLocalWorkSizeArray, null);
                                            Queue.Read <UInt32>(neoScryptOutputBuffer, true, 0, sNeoScryptOutputSize, (IntPtr)neoscryptOutputPtr, null);
                                            if (Stratum.GetJob() != null && Stratum.GetJob().Equals(neoscryptJob))
                                            {
                                                for (int i = 0; i < mNeoScryptOutput[255]; ++i)
                                                {
                                                    Stratum.Submit(Device, neoscryptWork, mNeoScryptOutput[i]);
                                                }
                                            }
                                            neoscryptStartNonce += (UInt32)mNeoScryptGlobalWorkSizeArray[0];

                                            sw.Stop();
                                            Speed = ((double)mNeoScryptGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds;
                                            Device.TotalHashesPrimaryAlgorithm += (double)mNeoScryptGlobalWorkSizeArray[0];
                                            if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                                            {
                                                MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Kh/s (NeoScrypt)", Speed / 1000));
                                                consoleUpdateStopwatch.Restart();
                                            }
                                        }
                                    }
                                } catch (Exception ex) {
                                    MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                                    if (UnrecoverableException.IsUnrecoverableException(ex))
                                    {
                                        this.UnrecoverableException = new UnrecoverableException(ex, Device);
                                        Stop();
                                    }
                                }

                                Speed = 0;

                                if (!Stopped)
                                {
                                    MainForm.Logger("Restarting miner thread...");
                                    System.Threading.Thread.Sleep(Parameters.WaitTimeForRestartingMinerThreadInMilliseconds);
                                }
                            }
            } catch (UnrecoverableException ex) {
                this.UnrecoverableException = ex;
            } catch (Exception ex) {
                this.UnrecoverableException = new UnrecoverableException(ex, Device);
            } finally {
                MarkAsDone();
                MemoryUsage = 0;
                if (program != null)
                {
                    program.Dispose(); program = null;
                }
                if (neoScryptGlobalCacheBuffer != null)
                {
                    OpenCLDevice.ReleaseComputeByteBuffer(neoScryptGlobalCacheBuffer); neoScryptGlobalCacheBuffer = null;
                }
            }
        }
Esempio n. 15
0
        protected override void ProcessLine(String line)
        {
            //MainForm.Logger("line: " + line);
            Dictionary <String, Object> response = JsonConvert.DeserializeObject <Dictionary <string, Object> >(line);

            if (response.ContainsKey("method") && response.ContainsKey("params"))
            {
                string method     = (string)response["method"];
                JArray parameters = (JArray)response["params"];
                if (method.Equals("mining.set_difficulty"))
                {
                    try  { mMutex.WaitOne(5000); } catch (Exception) { }
                    mDifficulty = (double)parameters[0];
                    try  { mMutex.ReleaseMutex(); } catch (Exception) { }
                    MainForm.Logger("Difficulty set to " + (double)parameters[0] + ".");
                }
                else if (method.Equals("mining.notify") && (mJob == null || mJob.ID != (string)parameters[0]))
                {
                    try { mMutex.WaitOne(5000); }
                    catch (Exception) { }
                    mJob = (new Job(this, (string)parameters[0], (string)parameters[1], (string)parameters[2], (string)parameters[3], (string)parameters[4], Array.ConvertAll(((JArray)parameters[5]).ToArray(), item => (string)item), (string)parameters[6], (string)parameters[7], (string)parameters[8]));
                    try  { mMutex.ReleaseMutex(); } catch (Exception) { }
                    MainForm.Logger("Received new job: " + parameters[0]);
                }
                else if (method.Equals("mining.set_extranonce"))
                {
                    try  { mMutex.WaitOne(5000); } catch (Exception) { }
                    mPoolExtranonce = (String)parameters[0];
                    try  { mMutex.ReleaseMutex(); } catch (Exception) { }
                    MainForm.Logger("Received new extranonce: " + parameters[0]);
                }
                else if (method.Equals("client.reconnect"))
                {
                    throw new Exception("client.reconnect");
                }
                else
                {
                    MainForm.Logger("Unknown stratum method: " + line);
                }
            }
            else if (response.ContainsKey("id") && response.ContainsKey("result"))
            {
                var  ID     = response["id"].ToString();
                bool result = (response["result"] == null) ? false : (bool)response["result"];

                if (ID == "3" && !result)
                {
                    throw (UnrecoverableException = new UnrecoverableException("Authorization failed."));
                }
                else if ((ID != "1" && ID != "2" && ID != "3") && result && !MainForm.DevFeeMode)
                {
                    MainForm.Logger("Share #" + ID + " accepted.");
                    ReportShareAcceptance();
                }
                else if ((ID != "1" && ID != "2" && ID != "3") && !result && !MainForm.DevFeeMode)
                {
                    MainForm.Logger("Share #" + ID + " rejected: " + (String)(((JArray)response["error"])[1]));
                    ReportShareRejection();
                }
            }
            else
            {
                MainForm.Logger("Unknown JSON message: " + line);
            }
        }
        override unsafe protected void MinerThread()
        {
            ComputeProgram       program           = null;
            ComputeBuffer <byte> statesBuffer      = null;
            ComputeBuffer <byte> scratchpadsBuffer = null;

            try {
                Random r          = new Random();
                var    openCLName = OpenCLDevice.GetComputeDevice().Name;
                var    GCN1       = openCLName == "Capeverde" || openCLName == "Hainan" || openCLName == "Oland" || openCLName == "Pitcairn" || openCLName == "Tahiti";

                MarkAsAlive();

                MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");
                MainForm.Logger("NiceHash mode is " + (NiceHashMode ? "on" : "off") + ".");

                program = BuildProgram("cryptonight", localWorkSizeA[0], "-O5" + (GCN1 ? " -legacy" : ""), "", "");

                statesBuffer      = OpenCLDevice.RequestComputeByteBuffer(ComputeMemoryFlags.ReadWrite, 200 * globalWorkSizeA[0]);
                scratchpadsBuffer = OpenCLDevice.RequestComputeByteBuffer(ComputeMemoryFlags.ReadWrite, ((long)1 << 21) * globalWorkSizeA[0]);

                using (var searchKernel0 = program.CreateKernel("search"))
                    using (var searchKernel1 = program.CreateKernel("search1"))
                        using (var searchKernel2 = program.CreateKernel("search2"))
                            using (var searchKernel3 = program.CreateKernel("search3"))
                                using (var inputBuffer = new ComputeBuffer <byte>(Context, ComputeMemoryFlags.ReadOnly, 76))
                                    using (var outputBuffer = new ComputeBuffer <UInt32>(Context, ComputeMemoryFlags.ReadWrite, outputSize))
                                        using (var terminateBuffer = new ComputeBuffer <Int32>(Context, ComputeMemoryFlags.ReadWrite, 1))
                                            fixed(Int32 *terminatePtr = terminate)
                                            fixed(byte *inputPtr     = input)
                                            fixed(UInt32 * outputPtr = output)
                                            while (!Stopped)
                                            {
                                                MarkAsAlive();
                                                MemoryUsage =
                                                    200 * globalWorkSizeA[0]
                                                    + ((long)1 << 21) * globalWorkSizeA[0]
                                                    + 76 + outputSize + 1;

                                                try {
                                                    searchKernel0.SetMemoryArgument(0, inputBuffer);
                                                    searchKernel0.SetMemoryArgument(1, scratchpadsBuffer);
                                                    searchKernel0.SetMemoryArgument(2, statesBuffer);

                                                    searchKernel1.SetMemoryArgument(0, scratchpadsBuffer);
                                                    searchKernel1.SetMemoryArgument(1, statesBuffer);
                                                    searchKernel1.SetMemoryArgument(2, terminateBuffer);

                                                    searchKernel2.SetMemoryArgument(0, scratchpadsBuffer);
                                                    searchKernel2.SetMemoryArgument(1, statesBuffer);

                                                    searchKernel3.SetMemoryArgument(0, statesBuffer);
                                                    searchKernel3.SetMemoryArgument(1, outputBuffer);

                                                    // Wait for the first job to arrive.
                                                    int elapsedTime = 0;
                                                    while ((Stratum == null || Stratum.GetJob() == null) && elapsedTime < Parameters.TimeoutForFirstJobInMilliseconds && !Stopped)
                                                    {
                                                        Thread.Sleep(100);
                                                        elapsedTime += 100;
                                                    }
                                                    if (Stratum == null || Stratum.GetJob() == null)
                                                    {
                                                        throw new TimeoutException("Stratum server failed to send a new job.");
                                                    }

                                                    System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                                                    CryptoNightStratum.Work      work;
                                                    CryptoNightStratum.Job       job;

                                                    while (!Stopped && (work = Stratum.GetWork()) != null && (job = work.GetJob()) != null)
                                                    {
                                                        MarkAsAlive();

                                                        Array.Copy(Utilities.StringToByteArray(job.Blob), input, 76);
                                                        byte   localExtranonce = (byte)work.LocalExtranonce;
                                                        byte[] targetByteArray = Utilities.StringToByteArray(job.Target);
                                                        UInt32 startNonce;
                                                        if (NiceHashMode)
                                                        {
                                                            startNonce = ((UInt32)input[42] << (8 * 3)) | ((UInt32)localExtranonce << (8 * 2)) | (UInt32)(r.Next(0, int.MaxValue) & (0x0000ffffu));
                                                        }
                                                        else
                                                        {
                                                            startNonce = ((UInt32)localExtranonce << (8 * 3)) | (UInt32)(r.Next(0, int.MaxValue) & (0x00ffffffu));
                                                        }
                                                        UInt32 target = ((UInt32)targetByteArray[0] << 0)
                                                                        | ((UInt32)targetByteArray[1] << 8)
                                                                        | ((UInt32)targetByteArray[2] << 16)
                                                                        | ((UInt32)targetByteArray[3] << 24);
                                                        searchKernel3.SetValueArgument <UInt32>(2, target);

                                                        Queue.Write <byte>(inputBuffer, true, 0, 76, (IntPtr)inputPtr, null);

                                                        consoleUpdateStopwatch.Start();

                                                        while (!Stopped && Stratum.GetJob() != null && Stratum.GetJob().Equals(job))
                                                        {
                                                            MarkAsAlive();

                                                            globalWorkOffsetA[0] = globalWorkOffsetB[0] = startNonce;

                                                            // Get a new local extranonce if necessary.
                                                            if (NiceHashMode)
                                                            {
                                                                if ((startNonce & 0xffff) + (UInt32)globalWorkSizeA[0] >= 0x10000)
                                                                {
                                                                    break;
                                                                }
                                                            }
                                                            else
                                                            {
                                                                if ((startNonce & 0xffffff) + (UInt32)globalWorkSizeA[0] >= 0x1000000)
                                                                {
                                                                    break;
                                                                }
                                                            }

                                                            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                                                            sw.Start();
                                                            output[255] = 0; // output[255] is used as an atomic counter.
                                                            Queue.Write <UInt32>(outputBuffer, true, 0, outputSize, (IntPtr)outputPtr, null);
                                                            terminate[0] = 0;
                                                            Queue.Write <Int32>(terminateBuffer, true, 0, 1, (IntPtr)terminatePtr, null);
                                                            Queue.Execute(searchKernel0, globalWorkOffsetA, globalWorkSizeA, localWorkSizeA, null);
                                                            Queue.Finish();
                                                            if (Stopped)
                                                            {
                                                                break;
                                                            }
                                                            Queue.Execute(searchKernel1, globalWorkOffsetB, globalWorkSizeB, localWorkSizeB, null);
                                                            Queue.Finish();
                                                            if (Stopped)
                                                            {
                                                                break;
                                                            }
                                                            Queue.Execute(searchKernel2, globalWorkOffsetA, globalWorkSizeA, localWorkSizeA, null);
                                                            Queue.Finish();
                                                            if (Stopped)
                                                            {
                                                                break;
                                                            }
                                                            Queue.Execute(searchKernel3, globalWorkOffsetB, globalWorkSizeB, localWorkSizeB, null);
                                                            Queue.Finish(); // Run the above statement before leaving the current local scope.
                                                            if (Stopped)
                                                            {
                                                                break;
                                                            }

                                                            Queue.Read <UInt32>(outputBuffer, true, 0, outputSize, (IntPtr)outputPtr, null);
                                                            if (Stratum.GetJob() != null && Stratum.GetJob().Equals(job))
                                                            {
                                                                for (int i = 0; i < output[255]; ++i)
                                                                {
                                                                    String result = "";
                                                                    for (int j = 0; j < 8; ++j)
                                                                    {
                                                                        UInt32 word = output[256 + i * 8 + j];
                                                                        result += String.Format("{0:x2}{1:x2}{2:x2}{3:x2}", ((word >> 0) & 0xff), ((word >> 8) & 0xff), ((word >> 16) & 0xff), ((word >> 24) & 0xff));
                                                                    }
                                                                    Stratum.Submit(Device, job, output[i], result);
                                                                }
                                                            }
                                                            startNonce += (UInt32)globalWorkSizeA[0];

                                                            sw.Stop();
                                                            Speed = ((double)globalWorkSizeA[0]) / sw.Elapsed.TotalSeconds;
                                                            Device.TotalHashesPrimaryAlgorithm += (double)globalWorkSizeA[0];
                                                            if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                                                            {
                                                                MainForm.Logger("Device #" + DeviceIndex + " (CryptoNight): " + String.Format("{0:N2} h/s", Speed));
                                                                consoleUpdateStopwatch.Restart();
                                                            }
                                                        }
                                                    }
                                                } catch (Exception ex) {
                                                    if (statesBuffer != null)
                                                    {
                                                        OpenCLDevice.ReleaseComputeByteBuffer(statesBuffer); statesBuffer = null;
                                                    }
                                                    if (scratchpadsBuffer != null)
                                                    {
                                                        OpenCLDevice.ReleaseComputeByteBuffer(scratchpadsBuffer); scratchpadsBuffer = null;
                                                    }
                                                    MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                                                    if (UnrecoverableException.IsUnrecoverableException(ex))
                                                    {
                                                        this.UnrecoverableException = new UnrecoverableException(ex, Device);
                                                        Stop();
                                                    }
                                                }

                                                Speed = 0;

                                                if (!Stopped)
                                                {
                                                    MainForm.Logger("Restarting miner thread...");
                                                    System.Threading.Thread.Sleep(Parameters.WaitTimeForRestartingMinerThreadInMilliseconds);
                                                }
                                            }
            } catch (UnrecoverableException ex) {
                this.UnrecoverableException = ex;
            } catch (Exception ex) {
                this.UnrecoverableException = new UnrecoverableException(ex, Device);
            } finally {
                MarkAsDone();
                MemoryUsage = 0;
                if (program != null)
                {
                    program.Dispose(); program = null;
                }
                if (statesBuffer != null)
                {
                    OpenCLDevice.ReleaseComputeByteBuffer(statesBuffer); statesBuffer = null;
                }
                if (scratchpadsBuffer != null)
                {
                    OpenCLDevice.ReleaseComputeByteBuffer(scratchpadsBuffer); scratchpadsBuffer = null;
                }
            }
        }
Esempio n. 17
0
        override unsafe protected void MinerThread()
        {
            Random r = new Random();

            MarkAsAlive();

            MainForm.Logger("Miner thread for Device #" + DeviceIndex + " started.");

            BuildLbryProgram();

            fixed(long *lbryGlobalWorkOffsetArrayPtr = mLbryGlobalWorkOffsetArray)
            fixed(long *lbryGlobalWorkSizeArrayPtr = mLbryGlobalWorkSizeArray)
            fixed(long *lbryLocalWorkSizeArrayPtr  = mLbryLocalWorkSizeArray)
            fixed(byte *lbryInputPtr     = mLbryInput)
            fixed(UInt32 * lbryOutputPtr = mLbryOutput)
            while (!Stopped)
            {
                MarkAsAlive();

                try
                {
                    mLbrySearchKernel.SetMemoryArgument(0, mLbryInputBuffer);
                    mLbrySearchKernel.SetMemoryArgument(1, mLbryOutputBuffer);

                    // Wait for the first lbryJob to arrive.
                    int elapsedTime = 0;
                    while ((mLbryStratum == null || mLbryStratum.GetJob() == null) && elapsedTime < 60000)
                    {
                        Thread.Sleep(100);
                        elapsedTime += 100;
                    }
                    if (mLbryStratum == null || mLbryStratum.GetJob() == null)
                    {
                        throw new TimeoutException("Stratum server failed to send a new lbryJob.");
                    }

                    System.Diagnostics.Stopwatch consoleUpdateStopwatch = new System.Diagnostics.Stopwatch();
                    LbryStratum.Work             lbryWork;

                    while (!Stopped && (lbryWork = mLbryStratum.GetWork()) != null)
                    {
                        MarkAsAlive();

                        var lbryJob = lbryWork.Job;
                        Array.Copy(lbryWork.Blob, mLbryInput, 112);
                        UInt32 lbryStartNonce = (UInt32)(r.Next(0, int.MaxValue));
                        UInt64 lbryTarget     = (UInt64)((double)0xffff0000UL / (mLbryStratum.Difficulty / 256));
                        mLbrySearchKernel.SetValueArgument <UInt64>(3, lbryTarget);
                        Queue.Write <byte>(mLbryInputBuffer, true, 0, 112, (IntPtr)lbryInputPtr, null);

                        consoleUpdateStopwatch.Start();

                        while (!Stopped && mLbryStratum.GetJob().Equals(lbryJob))
                        {
                            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                            sw.Start();

                            MarkAsAlive();

                            mLbrySearchKernel.SetValueArgument <UInt32>(2, lbryStartNonce);

                            // Get a new local extranonce if necessary.
                            if (0xffffffffu - lbryStartNonce < (UInt32)mLbryGlobalWorkSizeArray[0] * mIterations)
                            {
                                break;
                            }

                            mLbryOutput[255] = 0; // mLbryOutput[255] is used as an atomic counter.
                            Queue.Write <UInt32>(mLbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null);
                            Queue.Execute(mLbrySearchKernel, mLbryGlobalWorkOffsetArray, mLbryGlobalWorkSizeArray, mLbryLocalWorkSizeArray, null);
                            Queue.Read <UInt32>(mLbryOutputBuffer, true, 0, lbryOutputSize, (IntPtr)lbryOutputPtr, null);
                            if (mLbryStratum.GetJob().Equals(lbryJob))
                            {
                                for (int i = 0; i < mLbryOutput[255]; ++i)
                                {
                                    String result = "";
                                    for (int j = 0; j < 8; ++j)
                                    {
                                        UInt32 word = mLbryOutput[256 + i * 8 + j];
                                        result += String.Format("{0:x2}{1:x2}{2:x2}{3:x2}", ((word >> 0) & 0xff), ((word >> 8) & 0xff), ((word >> 16) & 0xff), ((word >> 24) & 0xff));
                                    }
                                    mLbryStratum.Submit(GatelessGateDevice, lbryWork, mLbryOutput[i], result);
                                }
                            }
                            lbryStartNonce += (UInt32)mLbryGlobalWorkSizeArray[0] * (uint)mIterations;

                            sw.Stop();
                            Speed = ((double)mLbryGlobalWorkSizeArray[0]) / sw.Elapsed.TotalSeconds * mIterations;
                            if (consoleUpdateStopwatch.ElapsedMilliseconds >= 10 * 1000)
                            {
                                MainForm.Logger("Device #" + DeviceIndex + ": " + String.Format("{0:N2} Mh/s (Lbry)", Speed / 1000000));
                                consoleUpdateStopwatch.Restart();
                            }
                        }
                    }
                } catch (Exception ex) {
                    MainForm.Logger("Exception in miner thread: " + ex.Message + ex.StackTrace);
                    if (UnrecoverableException.IsUnrecoverableException(ex))
                    {
                        this.UnrecoverableException = new UnrecoverableException(ex, GatelessGateDevice);
                        Stop();
                    }
                }

                Speed = 0;

                if (!Stopped)
                {
                    MainForm.Logger("Restarting miner thread...");
                    System.Threading.Thread.Sleep(5000);
                }
            }

            MarkAsDone();
        }