/// <summary> /// Starts reading plots for the specifed information and terminates and current plot mining. /// </summary> /// <param name="miningInfo"> /// The information to use to commence mining. /// </param> public void NotifyNewRound(MiningInfo miningInfo) { // Store this value _lastRoundStart = DateTime.UtcNow; _miningInfo = miningInfo; // First let's kill any existing plot reading foreach (PlotReader reader in _plotReaders) { reader.Terminate(); } // If no mining information stop now if (miningInfo == null) { return; } // Throw error if we have no readers if (_plotReaders == null) { Logger.Warn("Unable to process new block " + miningInfo.BlockHeight + ", no plot readers available"); return; } // Now we perform our basics to determine scoop number byte[] gensigHashable = new byte[40]; Array.Copy(miningInfo.PreviousGenerationSignatureBytes, gensigHashable, 32); Array.Copy(miningInfo.BlockHeightBytes, 0, gensigHashable, 32, 8); byte[] gensig = _shabel.ComputeBytes(gensigHashable).GetBytes(); uint scoop = (uint)((gensig[gensig.Length - 2] & 0x0F) << 8) | (gensig[gensig.Length - 1]); Logger.Debug("Calculated scoop for block as " + scoop); // Update our capacity values decimal utilisedStorage = 0; foreach (PlotReader reader in _plotReaders) { utilisedStorage += reader.UtilisedStorage; } if (UtilisedStorage != utilisedStorage) { UtilisedStorage = utilisedStorage; UtilisedStorageUpdated?.Invoke(this, new UtilisedStorageEventHandler(utilisedStorage)); } // With the config that we have we can now execute all of our readers foreach (PlotReader reader in _plotReaders) { reader.StartMining(miningInfo, scoop); } }
/// <summary> /// The main entry point for the threads that individually check for deadlines. /// </summary> private void ThreadEntry() { Shabal256 shabal = new Shabal256(); byte[] hashBuffer = new byte[32 + Plot.SCOOP_SIZE]; ulong lastBlockHeightPrevGenCopied = 0; while (_isAlive) { // Get a few items from the queue to process Scoop[] scoops; lock (_scoopQueueLocker) { scoops = new Scoop[_scoopQueue.Count > 100 ? 100 : _scoopQueue.Count]; if (scoops.Length > 0) { for (int i = 0; i < scoops.Length; i++) { scoops[i] = _scoopQueue[_scoopQueue.Count - i - 1]; } _scoopQueue.RemoveRange(_scoopQueue.Count - scoops.Length, scoops.Length); } } // If we didn't get an item or if for some reason the mining info has been wiped wait and try again if (scoops == null || scoops.Length < 1) { Thread.Sleep(200); continue; } foreach (Scoop scoop in scoops) { // Breakout if we're no longer running MiningInfo miningInfo = _miningInfo; if (!_isAlive || miningInfo == null) { break; } // Ensure we're on right block if (scoop.BlockHeight != miningInfo.BlockHeight) { continue; } // Calculate the deadline for this scoop if (lastBlockHeightPrevGenCopied != miningInfo.BlockHeight) { Array.Copy(_miningInfo.PreviousGenerationSignatureBytes, hashBuffer, 32); lastBlockHeightPrevGenCopied = miningInfo.BlockHeight; } Array.Copy(scoop.Data, 0, hashBuffer, 32, Plot.SCOOP_SIZE); byte[] target = shabal.ComputeBytes(hashBuffer).GetBytes(); ulong targetResult = BitConverter.ToUInt64(target, 0); // And with our target compute a deadline ulong deadline = targetResult / miningInfo.BaseTarget; if (deadline < miningInfo.Deadline) { DeadlineFound?.Invoke(this, new DeadlineFoundEventArgs(deadline, scoop, miningInfo)); } } } }