private EthereumBlockTemplate AssembleBlockTemplate(string[] work) { // only parity returns the 4th element (block height) if (work.Length < 4) { logger.Error(() => $"[{LogCat}] Error(s) refreshing blocktemplate: getWork did not return blockheight. Are you really connected to a Parity daemon?"); return(null); } // extract values var height = work[3].IntegralFromHex <ulong>(); var targetString = work[2]; var target = BigInteger.Parse(targetString.Substring(2), NumberStyles.HexNumber); var result = new EthereumBlockTemplate { Header = work[0], Seed = work[1], Target = targetString, Difficulty = (ulong)BigInteger.Divide(EthereumConstants.BigMaxValue, target), Height = height, }; return(result); }
private EthereumBlockTemplate AssembleBlockTemplate(Block block, string[] work) { // only parity returns the 4th element (block height) if (work.Length < 3) { logger.Error(() => $"[{LogCat}] Error(s) refreshing blocktemplate: getWork did not return blockheight. Are you really connected to a Parity daemon?"); return(null); } // make sure block matches work var height = work[3].IntegralFromHex <ulong>(); if (height != block.Height) { logger.Debug(() => $"[{LogCat}] Discarding block template update as getWork result is not related to pending block"); return(null); } var result = new EthereumBlockTemplate { Header = work[0], Seed = work[1], Target = work[2], Difficulty = block.Difficulty.IntegralFromHex <ulong>(), Height = block.Height.Value, ParentHash = block.ParentHash, }; return(result); }
private async Task <EthereumBlockTemplate> GetBlockTemplateAsync() { logger.LogInvoke(LogCat); var commands = new[] { new DaemonCmd(EC.GetBlockByNumber, new[] { (object)"pending", true }), new DaemonCmd(EC.GetWork), }; var results = await daemon.ExecuteBatchAnyAsync(commands); if (results.Any(x => x.Error != null)) { var errors = results.Where(x => x.Error != null) .ToArray(); if (errors.Any()) { logger.Warn(() => $"[{LogCat}] Error(s) refreshing blocktemplate: {string.Join(", ", errors.Select(y => y.Error.Message))})"); return(null); } } // extract results var block = results[0].Response.ToObject <Block>(); var work = results[1].Response.ToObject <string[]>(); // only parity returns the 4th element (block height) if (work.Length < 3) { logger.Error(() => $"[{LogCat}] Error(s) refreshing blocktemplate: getWork did not return blockheight. Are you really connected to a Parity daemon?"); return(null); } // make sure block matches work var height = work[3].IntegralFromHex <ulong>(); if (height != block.Height) { logger.Debug(() => $"[{LogCat}] Discarding block template update as getWork result is not related to pending block"); return(null); } var result = new EthereumBlockTemplate { Header = work[0], Seed = work[1], Target = BigInteger.Parse("0" + work[2].Substring(2), NumberStyles.HexNumber), Difficulty = block.Difficulty.IntegralFromHex <ulong>(), Height = block.Height.Value, ParentHash = block.ParentHash, }; return(result); }
protected bool UpdateJob(EthereumBlockTemplate blockTemplate) { logger.LogInvoke(LogCat); try { // may happen if daemon is currently not connected to peers if (blockTemplate == null || blockTemplate.Header?.Length == 0) { return(false); } var job = currentJob; var isNew = currentJob == null || job.BlockTemplate.Header != blockTemplate.Header; if (isNew) { var jobId = NextJobId("x8"); // update template job = new EthereumJob(jobId, blockTemplate, logger); lock (jobLock) { // add jobs validJobs[jobId] = job; // remove old ones var obsoleteKeys = validJobs.Keys .Where(key => validJobs[key].BlockTemplate.Height < job.BlockTemplate.Height - MaxBlockBacklog).ToArray(); foreach (var key in obsoleteKeys) { validJobs.Remove(key); } } currentJob = job; // update stats BlockchainStats.LastNetworkBlockTime = clock.Now; BlockchainStats.BlockHeight = (long)job.BlockTemplate.Height; BlockchainStats.NetworkDifficulty = job.BlockTemplate.Difficulty; } return(isNew); } catch (Exception ex) { logger.Error(ex, () => $"[{LogCat}] Error during {nameof(UpdateJob)}"); } return(false); }
public EthereumJob(EthereumBlockTemplate blockTemplate, byte[] instanceId, string jobId, PoolConfig poolConfig, ClusterConfig clusterConfig) { Contract.RequiresNonNull(blockTemplate, nameof(blockTemplate)); Contract.RequiresNonNull(poolConfig, nameof(poolConfig)); Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig)); Contract.RequiresNonNull(instanceId, nameof(instanceId)); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty"); BlockTemplate = blockTemplate; }
public EthereumJob(string id, EthereumBlockTemplate blockTemplate) { Id = id; BlockTemplate = blockTemplate; var target = blockTemplate.Target; if (target.StartsWith("0x")) { target = target.Substring(2); } blockTarget = new uint256(target.HexToByteArray().ReverseArray()); }
private async Task <EthereumBlockTemplate> GetBlockTemplateAsync() { var commands = new[] { new DaemonCmd(EC.GetBlockByNumber, new[] { (object)"pending", true }), new DaemonCmd(EC.GetWork), }; var results = await daemon.ExecuteBatchAnyAsync(commands); if (results.Any(x => x.Error != null)) { var errors = results.Where(x => x.Error != null) .ToArray(); if (errors.Any()) { logger.Warn(() => $"[{LogCat}] Error(s) refreshing blocktemplate: {string.Join(", ", errors.Select(y => y.Error.Message))})"); return(null); } } // extract results var block = results[0].Response.ToObject <Block>(); var work = results[1].Response.ToObject <string[]>(); var result = new EthereumBlockTemplate { Header = work[0].HexToByteArray(), Seed = work[1].HexToByteArray(), Target = new BigInteger(work[2].HexToByteArray().ToReverseArray()), // BigInteger.Parse(work[2], NumberStyles.HexNumber | NumberStyles.AllowHexSpecifier) Difficulty = block.Difficulty.IntegralFromHex <ulong>(), Height = block.Height.Value, ParentHash = block.ParentHash, }; return(result); }
public EthereumJob(string id, EthereumBlockTemplate blockTemplate) { Id = id; BlockTemplate = blockTemplate; }