protected virtual byte[] SerializeHeader(uint nTime, byte[] extraNonce, uint nonce) { byte[] serialized; using (var stream = new MemoryStream()) { var bs = new BitcoinStream(stream, true); BlockHeader.ReadWrite(bs); serialized = stream.ToArray(); } var tmpBlockHeader = new CommerciumBlockHeader(serialized); tmpBlockHeader.Timestamp = nTime; tmpBlockHeader.Nonce = nonce; Array.Resize(ref extraNonce, 32); tmpBlockHeader.ExtraData = extraNonce; byte[] serializedTmp; using (var stream = new MemoryStream()) { var bs = new BitcoinStream(stream, true); tmpBlockHeader.ReadWriteWithoutSolution(bs); serializedTmp = stream.ToArray(); } return(serializedTmp); }
public virtual void Init(CommerciumGetWork work, string jobId, PoolConfig poolConfig, ClusterConfig clusterConfig, IMasterClock clock, IDestination poolAddressDestination, BitcoinNetworkType networkType, double shareMultiplier, decimal blockrewardMultiplier, IHashAlgorithm headerHasher) { Contract.RequiresNonNull(work, nameof(work)); Contract.RequiresNonNull(poolConfig, nameof(poolConfig)); Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig)); Contract.RequiresNonNull(clock, nameof(clock)); Contract.RequiresNonNull(poolAddressDestination, nameof(poolAddressDestination)); Contract.RequiresNonNull(headerHasher, nameof(headerHasher)); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty"); this.clock = clock; if (CommerciumConstants.Chains.TryGetValue(poolConfig.Coin.Type, out var chain)) { chain.TryGetValue(networkType, out chainConfig); } Work = work; BlockHeader = new CommerciumBlockHeader(work.Data); JobId = jobId; this.shareMultiplier = shareMultiplier; this.headerHasher = headerHasher; blockTarget = new Target(BlockHeader.Bits); Difficulty = chainConfig.Diff1.Divide(blockTarget.ToBigInteger()).LongValue; BuildCoinbase(); jobParams = new object[] { JobId, BlockHeader.PrevBlock.ToHexString(), coinbaseInitialHex, coinbaseFinalHex, "", BlockHeader.Version.ToStringHex8().HexToByteArray().ReverseArray().ToHexString(), BlockHeader.Bits.ReverseByteOrder().ToStringHex8(), BlockHeader.Timestamp.ReverseByteOrder().ToStringHex8(), false }; }
protected virtual async Task <(bool IsNew, bool Force)> UpdateJob(bool forceUpdate, string via = null, string json = null) { logger.LogInvoke(LogCat); try { if (forceUpdate) { _lastJobRebroadcast = _clock.Now; } var response = string.IsNullOrEmpty(json) ? await GetWorkAsync() : GetWorkFromJson(json); // may happen if daemon is currently not connected to peers if (response.Error != null) { logger.Warn(() => $"[{LogCat}] Unable to update job. Daemon responded with: {response.Error.Message} Code {response.Error.Code}"); return(false, forceUpdate); } var work = response.Response; var blockHeader = new CommerciumBlockHeader(work.Data); var job = currentJob; var isNew = job == null || (job.BlockHeader?.PrevBlock != blockHeader.PrevBlock && blockHeader.Height > job.BlockHeader?.Height); if (isNew || forceUpdate) { job = new CommerciumJob(); job.Init(work, NextJobId(), poolConfig, clusterConfig, _clock, _poolAddressDestination, _networkType, ShareMultiplier, _extraPoolPaymentProcessingConfig?.BlockrewardMultiplier ?? 1.0m, _headerHasher); lock (jobLock) { if (isNew) { if (via != null) { logger.Info(() => $"[{LogCat}] Detected new block {blockHeader.Height} via {via}"); } else { logger.Info(() => $"[{LogCat}] Detected new block {blockHeader.Height}"); } _validJobs.Clear(); // update stats BlockchainStats.LastNetworkBlockTime = _clock.Now; BlockchainStats.BlockHeight = blockHeader.Height; BlockchainStats.NetworkDifficulty = job.Difficulty; } else { // trim active jobs while (_validJobs.Count > _maxActiveJobs - 1) { _validJobs.RemoveAt(0); } } _validJobs.Add(job); } currentJob = job; } return(isNew, forceUpdate); } catch (Exception ex) { logger.Error(ex, () => $"[{LogCat}] Error during {nameof(UpdateJob)}"); } return(false, forceUpdate); }