/// <summary> /// Sets the current mining mission. /// </summary> /// <param name="wp">The work package we wish to be mining.</param> public void SetWork(WorkPackage wp) { if (_currentWp.Epoch != wp.Epoch) { //var ec = Ethash.GetGlobalEpochContext(wp.Epoch); //_currentEc.EpochNumber = wp.Epoch; //_currentEc.LightNumItems = ec.LightCacheNumItems; //_currentEc.LightSize = Ethash.GetLightCacheSize(ec.LightCacheNumItems); //_currentEc.DagNumItems = ec.FullDatasetNumItems; //_currentEc.DagSize = Ethash.GetFullDatasetSize(ec.FullDatasetNumItems); //_currentEc.LightCache = ec.LightCcache; foreach (var miner in _miners) { miner.SetEpoch(_currentEc); } } _currentWp = wp; // Check if we need to shuffle per work (ergodicity == 2) if (_options.Ergodicity == 2 && _currentWp.ExSizeBytes == 0) { Shuffle(); } ulong startNonce; if (_currentWp.ExSizeBytes > 0) { // Equally divide the residual segment among miners startNonce = _currentWp.StartNonce; _nonceSegmentWidth = (int)Math.Log(Math.Pow(2, 64 - (_currentWp.ExSizeBytes * 4)) / _miners.Count, 2); } // Get the randomly selected nonce else { startNonce = _nonceScrambler; } for (var i = 0; i < _miners.Count; i++) { _currentWp.StartNonce = startNonce + ((ulong)i << _nonceSegmentWidth); _miners[i].SetWork(_currentWp); } }
public void SetWork(WorkPackage currentWp) { throw new NotImplementedException(); }
void SetClientHandlers() { _client.OnConnected((f, c) => { var connection = c.Connection; // If HostName is already an IP address no need to append the effective ip address. if ((connection.HostNameType == UriHostNameType.Dns || connection.HostNameType == UriHostNameType.Basic) && !string.IsNullOrEmpty(c.ActiveEndPoint)) { _selectedHost = connection.Host + c.ActiveEndPoint; } Console.WriteLine($"Established connection to {_selectedHost}"); _connectionAttempt = 0; // Reset current WorkPackage _currentWp.Job = null; _currentWp.Header = H256.Empty; // Shuffle if needed if (f.Ergodicity == 1U) { f.Shuffle(); } // Rough implementation to return to primary pool after specified amount of time _failoverTimer = _activeConnectionIdx != 0 && _options.PoolFailoverTimeout != 0 ? new Timer(FailoverTimer_Elapsed, null, new TimeSpan(0, _options.PoolFailoverTimeout, 0), new TimeSpan(0, 0, -1)) : null; if (!f.IsMining) { Console.WriteLine("Spinning up miners..."); f.Start(); } else if (f.Paused) { Console.WriteLine("Resume mining ..."); f.Resume(); } // Activate timing for HR submission _submithrTimer = _options.ReportHashrate ? new Timer(SubmithrTimer_Elapsed, null, new TimeSpan(0, 0, _options.HashRateInterval), new TimeSpan(0, 0, -1)) : null; // Signal async operations have completed _asyncPending = 0; //: atomic }); _client.OnDisconnected((f, c) => { Console.WriteLine($"Disconnected from {_selectedHost}"); // Clear current connection c.UnsetConnection(); _currentWp.Header = H256.Empty; // Stop timing actors _failoverTimer?.Dispose(); _failoverTimer = null; _submithrTimer?.Dispose(); _submithrTimer = null; if (_stopping != 0) //: atomic { if (f.IsMining) { Console.WriteLine("Shutting down miners..."); f.Stop(); } _running = 0; //: atomic } else { // Signal we will reconnect async _asyncPending = 1; //: atomic // Suspend mining and submit new connection request Console.WriteLine("No connection. Suspend mining ..."); f.Pause(); Task.Run(() => RotateConnect()); } }); _client.OnWorkReceived((f, c, wp) => { // Should not happen ! if (wp == null) { return; } var _currentEpoch = _currentWp.Epoch; var newEpoch = _currentEpoch == -1; // In EthereumStratum/2.0.0 epoch number is set in session if (!newEpoch) { newEpoch = c.Connection.GetStratumMode() == StratumVersion.EthereumStratum2 ? wp.Epoch != _currentWp.Epoch : wp.Seed != _currentWp.Seed; } var newDiff = wp.Boundary != _currentWp.Boundary; _currentWp = wp; if (newEpoch) { Interlocked.Add(ref _epochChanges, 1); // If epoch is valued in workpackage take it if (wp.Epoch == -1) { _currentWp.Epoch = _currentWp.Block >= 0 ? _currentWp.Block / 30000 : Ethash.FindEpochNumber(Ethash.Hash256FromBytes(_currentWp.Seed.Data)); } } else { _currentWp.Epoch = _currentEpoch; } if (newDiff || newEpoch) { ShowMiningAt(); } Console.WriteLine($"Job: {Ansi.White}{_currentWp.Header.Abridged}{(_currentWp.Block != -1 ? $" block {_currentWp.Block}" : null)}{Ansi.Reset} {_selectedHost}"); f.SetWork(_currentWp); }); _client.OnSolutionAccepted((f, c, responseDelay, minerIdx, asStale) => { Console.WriteLine($"{Ansi.Lime}**Accepted{(asStale ? " stale" : null)}{Ansi.Reset}{responseDelay,4} ms. {_selectedHost}"); f.AccountSolution(minerIdx, SolutionAccounting.Accepted); }); _client.OnSolutionRejected((f, c, responseDelay, minerIdx) => { Console.WriteLine($"{Ansi.Red}**Rejected{Ansi.Reset}{responseDelay,4} ms. {_selectedHost}"); f.AccountSolution(minerIdx, SolutionAccounting.Rejected); }); }